summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-04-27 22:33:55 +0800
committerruki <[email protected]>2025-08-28 11:35:53 +0800
commit8b976dd744fc18d617e00655631cbca8a1f19035 (patch)
tree058fdb2342441ac49e7123fe6ae96f5fed4d7aee
parentec3153a9254fb8d3f93371b4026dc1000afcae7c (diff)
optimize thread load/save
-rw-r--r--xmake/core/base/serialize.lua42
-rw-r--r--xmake/core/thread/thread.lua57
2 files changed, 59 insertions, 40 deletions
diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua
index 665fe04a6..87c810536 100644
--- a/xmake/core/base/serialize.lua
+++ b/xmake/core/base/serialize.lua
@@ -25,12 +25,26 @@ local stub = serialize._stub or {}
serialize._stub = stub
serialize._dump = serialize._dump or string._dump or string.dump
serialize._BCTAG = xmake._LUAJIT and "\27LJ" or "\27Lua"
+stub.isstub = setmetatable({}, { __tostring = function() return "stub indentifier" end })
+stub.__index = stub
-- load modules
local math = require("base/math")
local table = require("base/table")
local hashset = require("base/hashset")
+function stub:__call(root, fenv)
+ return self.resolver(root, fenv, table.unpack(self.params, 1, self.params.n))
+end
+
+function stub:__tostring()
+ local fparams = {}
+ for i = 1, self.params.n do
+ fparams[i] = serialize._make(self.params[i], {})
+ end
+ return string.format("%s(%s)", self.name, table.concat(fparams, ", "))
+end
+
-- reserved keywords in lua
function serialize._keywords()
local keywords = serialize._KEYWORDS
@@ -339,22 +353,6 @@ function serialize.save(obj, opt)
return (#dump < #result) and dump or result
end
--- init stub metatable
-stub.isstub = setmetatable({}, { __tostring = function() return "stub indentifier" end })
-stub.__index = stub
-
-function stub:__call(root, fenv)
- return self.resolver(root, fenv, table.unpack(self.params, 1, self.params.n))
-end
-
-function stub:__tostring()
- local fparams = {}
- for i = 1, self.params.n do
- fparams[i] = serialize._make(self.params[i], {})
- end
- return string.format("%s(%s)", self.name, table.concat(fparams, ", "))
-end
-
-- called by functions in deserialize environment
-- create a function (called stub) to finish deserialization
function serialize._createstub(name, resolver, env, ...)
@@ -408,23 +406,13 @@ end
-- create a env for deserialze load() call
function serialize._createenv()
-
- -- init env
local env = { nan = math.nan, inf = math.huge }
-
- -- resolve reference
function env.ref(...)
- -- load ref
return serialize._createstub("ref", serialize._resolveref, env, ...)
end
-
- -- load function
function env.func(...)
- -- load func
return serialize._createstub("func", serialize._resolvefunction, env, ...)
end
-
- -- return new env
return env
end
@@ -442,7 +430,6 @@ function serialize._load(str)
local env = serialize._createenv()
local script, errors = load(str, binary and "=(b)" or "=(t)", binary and "b" or "t", env)
if script then
- -- load obj
local ok, obj = pcall(script)
if ok then
result = obj
@@ -451,7 +438,6 @@ function serialize._load(str)
result, errors = serialize._resolvestub(result, result, fenv, "<root>")
end
else
- -- error
errors = tostring(obj)
end
end
diff --git a/xmake/core/thread/thread.lua b/xmake/core/thread/thread.lua
index 9571c981b..dcb74e282 100644
--- a/xmake/core/thread/thread.lua
+++ b/xmake/core/thread/thread.lua
@@ -92,11 +92,12 @@ function _instance:start()
assert(not self:cdata())
-- serialize and pass callback and arguments to this thread
- local callinfo = {
- callback = self._CALLBACK,
- argv = self._ARGV
- }
- callinfo = string.serialize(callinfo, {strip = true, indent = false})
+ -- we do not use string.serialize to serialize callback, because it's slower (deserialize)
+ local callinfo = string._dump(self._CALLBACK, true)
+ local argv = self._ARGV
+ if argv ~= nil then
+ callinfo = string.serialize(argv, {strip = true, indent = false}) .. "<Argv\27>" .. callinfo
+ end
-- init and start thread
local handle, errors = thread.thread_init(self:name(), callinfo, self._STACKSIZE)
@@ -205,14 +206,46 @@ end
-- run thread
function thread._run_thread(callinfo_str)
- -- get callback info
- local callinfo, errors = string.deserialize(callinfo_str)
- if not callinfo then
- return false, string.format("invalid thread callinfo, %s!", errors or "unknown")
+ -- get callinfo
+ local parts = callinfo_str:split("<Argv\27>", {plain = true})
+ local callback_str, argv_str
+ if #parts > 1 then
+ callback_str = parts[2]
+ argv_str = parts[1]
+ else
+ callback_str = parts[1]
+ end
+
+ -- load callback
+ local fenv = debug.getfenv(debug.getinfo(2, "f").func)
+ local callback
+ if callback_str then
+ local script, errors = load(callback_str, "=(thread)", "b", fenv)
+ if not script then
+ return false, string.format("cannot load thread callback, %s!", errors or "unknown")
+ end
+ --[[
+ for i = 1, math.huge do
+ local upname, upvalue = debug.getupvalue(script, i)
+ if upname == nil or upname == "" then
+ break
+ end
+ print("upname", i, upname, upvalue)
+ end]]
+ callback = script
end
- local callback = callinfo.callback
if not callback then
- return false, string.format("no callback")
+ return false, "no thread callback"
+ end
+
+ -- load argument list
+ local argv
+ if argv_str then
+ local result, errors = string.deserialize(argv_str)
+ if not result then
+ return false, string.format("invalid thread arguments, %s!", errors or "unknown")
+ end
+ argv = result
end
-- bind sandbox
@@ -224,7 +257,7 @@ function thread._run_thread(callinfo_str)
end
-- do callback
- return sandbox.load(sandbox_inst:script(), table.unpack(callinfo.argv or {}))
+ return sandbox.load(sandbox_inst:script(), table.unpack(argv or {}))
end
-- return module