xtype (halted)

Check-in [304a118a3a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add micro benchmarks and improve performances. - Prevent UCLO NYI bytecode for LuaJIT. - Don't use globals in hotspots.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 304a118a3a9345ef7fbf0b755b3b117c7e534d49821039b09cec88e0db0f1376
User & Date: imagic 2021-11-14 18:01:48.000
Context
2021-11-18
16:01
Release 1.0. ... (check-in: 09d75937b5 user: imagic tags: trunk, 1.0)
2021-11-14
18:01
Add micro benchmarks and improve performances. ... (check-in: 304a118a3a user: imagic tags: trunk)
18:01
Handle multifunction candidates ambiguity. ... (check-in: ac195a58b8 user: imagic tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Deleted examples/bench_call.lua.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- Benchmark multifunction call.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

local n = ...
n = tonumber(n) or 1e6

local add = xtype.multifunction()
add:define(function(a,b) return a+b end, "number", "number")

local a = 0
for i=1,n do
  a = add(a, 1)
end
assert(a == n)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Deleted examples/bench_check.lua.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- Benchmark type checking.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

local n = ...
n = tonumber(n) or 1e7

local T = xtype.create("T")
local t = setmetatable({}, {xtype = T})

local a
for i=1,n do
  a = xtype.is(T, "xtype") and xtype.is(t, T) and xtype.is(i, "number")
end
assert(a)
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Added examples/bench_entities_call.lua.






















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- Benchmark multifunction call.
package.path = "src/?.lua;"..package.path

local xtype = require("xtype")

local Entity = xtype.create("Entity")
local Player = xtype.create("Player", Entity)
local Mob = xtype.create("Mob", Entity)

local f = xtype.multifunction()
local entities = {}
local player_count = 0
for i=1,1e3 do
  local T = math.random() <= 1/2 and Player or Mob
  if T == Player then player_count = player_count+1 end
  table.insert(entities, setmetatable({}, {xtype = T}))
end

local n = ...; n = tonumber(n) or 1e4
local count
f:define(function() count=count+1 end, Player)
f:define(function() end, Mob)
for i=1, n do
  count = 0
  for _, entity in ipairs(entities) do f(entity) end
  assert(count == player_count)
end
Added examples/bench_entities_check.lua.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- Benchmark type checking.
package.path = "src/?.lua;"..package.path

local xtype = require("xtype")

local Entity = xtype.create("Entity")
local Player = xtype.create("Player", Entity)
local Mob = xtype.create("Mob", Entity)

local entities = {}
local player_count = 0
for i=1,1e3 do
  local T = math.random() <= 1/2 and Player or Mob
  if T == Player then player_count = player_count+1 end
  table.insert(entities, setmetatable({}, {xtype = T}))
end

local n = ...; n = tonumber(n) or 1e4
for i=1, n do
  local count = 0
  for _, entity in ipairs(entities) do
    if xtype.is(entity, Player) then count = count+1 end
  end
  assert(count == player_count)
end
Changes to src/xtype.lua.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
local ffi
do
  local ok; ok, ffi = pcall(require, "ffi")
  ffi = ok and ffi or nil
end
local loadstring = loadstring or load
local table_unpack = table.unpack or unpack
local type, select = type, select
local table_pack = table.pack or function(...)
  local t = {...}
  t.n = select("#", ...)
  return t
end

local function error_arg(index, expected)







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
local ffi
do
  local ok; ok, ffi = pcall(require, "ffi")
  ffi = ok and ffi or nil
end
local loadstring = loadstring or load
local table_unpack = table.unpack or unpack
local type, select, getmetatable, pcall = type, select, getmetatable, pcall
local table_pack = table.pack or function(...)
  local t = {...}
  t.n = select("#", ...)
  return t
end

local function error_arg(index, expected)
84
85
86
87
88
89
90


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  if t and not ctype_types[id] then
    check_type(t, 2)
    ctype_types[id] = t
  end
  return ctype_types[id]
end



-- Get terminal type of a value.
local function xtype_get(v)
  local v_type = type(v)
  if v_type == "table" or v_type == "userdata" then
    local mt = getmetatable(v)
    return mt and mt.xtype or v_type
  elseif v_type == "cdata" then
    local xt = ctype_types[tonumber(ffi.typeof(v))]
    if not xt then -- try to acquire type from field
      local ok; ok, xt = pcall(function(v) return v.__xtype end, v)
      if ok then xtype.ctype(ffi.typeof(v), xt) end
    end
    return xt or v_type
  else return v_type end
end
xtype.get = xtype_get








>
>









|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  if t and not ctype_types[id] then
    check_type(t, 2)
    ctype_types[id] = t
  end
  return ctype_types[id]
end

local function cdata_get(v) return v.__xtype end

-- Get terminal type of a value.
local function xtype_get(v)
  local v_type = type(v)
  if v_type == "table" or v_type == "userdata" then
    local mt = getmetatable(v)
    return mt and mt.xtype or v_type
  elseif v_type == "cdata" then
    local xt = ctype_types[tonumber(ffi.typeof(v))]
    if not xt then -- try to acquire type from field
      local ok; ok, xt = pcall(cdata_get, v)
      if ok then xtype.ctype(ffi.typeof(v), xt) end
    end
    return xt or v_type
  else return v_type end
end
xtype.get = xtype_get