Testing new optimization features

This commit is contained in:
Ryan Ward 2022-10-24 23:24:24 -04:00
parent 7353fde799
commit e5ac4d3d9e
4 changed files with 230 additions and 78 deletions

View File

@ -29,6 +29,7 @@ local clock = os.clock
local thread = {}
local in_proc = false
local processes = {}
local find_optimization = false
if not _G["$multi"] then
_G["$multi"] = {multi=multi,thread=thread}
@ -113,7 +114,11 @@ end
function multi.ForEach(tab,func)
for i=1,#tab do func(tab[i]) end
end
local CRef = {
Fire = function() end
}
local optimization_stats = {}
local ignoreconn = true
function multi:newConnection(protect,func,kill)
local c={}
@ -128,9 +133,12 @@ function multi:newConnection(protect,func,kill)
for i,v in pairs(t) do
if v==self then
local ref = self:Connect(select(2,...))
if ref then
ref.root_link = select(1,...)
return ref
end
return self
end
end
return self:Connect(...)
else
@ -207,7 +215,10 @@ function multi:newConnection(protect,func,kill)
if lock then return end
for i=#call_funcs,1,-1 do
if not call_funcs[i] then return end
pcall(call_funcs[i],...)
local suc, err = pcall(call_funcs[i],...)
if not suc then
print(err)
end
if kill then
table.remove(call_funcs,i)
end
@ -231,6 +242,7 @@ function multi:newConnection(protect,func,kill)
end
function c:fastMode()
if find_optimization then return self end
function self:Fire(...)
for i=1,#fast do
fast[i](...)
@ -341,16 +353,39 @@ function multi:newConnection(protect,func,kill)
return self
end
if find_optimization then
--
end
c.connect=c.Connect
c.GetConnection=c.getConnection
c.HasConnections = c.hasConnections
c.GetConnection = c.getConnection
if not(ignoreconn) then
multi:create(c)
end
return c
end
multi.enableOptimization = multi:newConnection()
multi.optConn = multi:newConnection(true)
multi.optConn(function(msg)
table.insert(optimization_stats, msg)
end)
function multi:getOptimizationConnection()
return multi.optConn
end
function multi:getOptimizationStats()
return optimization_stats
end
function multi:isFindingOptimizing()
return find_optimization
end
-- Used with ISO Threads
local function isolateFunction(func,env)
local dmp = string.dump(func)
@ -531,10 +566,6 @@ function multi:newConnector()
return c
end
local CRef = {
Fire = function() end
}
multi.OnObjectCreated=multi:newConnection()
multi.OnObjectDestroyed=multi:newConnection()
multi.OnLoad = multi:newConnection(nil,nil,true)
@ -1093,6 +1124,62 @@ function thread.hold(n,opt)
end
end
function thread.hold(n,opt)
thread._Requests()
local opt = opt or {}
if type(opt)=="table" then
interval = opt.interval
if opt.cycles then
return yield(CMD, t_holdW, opt.cycles or 1, n or dFunc, interval)
elseif opt.sleep then
return yield(CMD, t_holdF, opt.sleep, n or dFunc, interval)
elseif opt.skip then
return yield(CMD, t_skip, opt.skip or 1, nil, interval)
end
end
if type(n) == "number" then
thread.getRunningThread().lastSleep = clock()
return yield(CMD, t_sleep, n or 0, nil, interval)
elseif type(n) == "table" and n.Type == "connector" then
local rdy = function()
return false
end
n(function(a1,a2,a3,a4,a5,a6)
rdy = function()
if a1==nil then
return NIL,a2,a3,a4,a5,a6
end
return a1,a2,a3,a4,a5,a6
end
end)
return yield(CMD, t_hold, function()
return rdy()
end, nil, interval)
elseif type(n) == "function" then
if find_optimization then
local cache = string.dump(n)
local f_str = tostring(n)
local good = true
for i=1,#func_cache do
if func_cache[i][1] == cache and func_cache[i][2] ~= f_str then
if not func_cache[i][3] then
multi.optConn:Fire("It's better to store a function to a variable than to use an anonymous function within the hold method!\n" .. debug.traceback())
func_cache[i][3] = true
end
good = false
end
end
if good then
table.insert(func_cache, {cache, f_str})
end
end
return yield(CMD, t_hold, n or dFunc, nil, interval)
else
error("Invalid argument passed to thread.hold(...)!")
end
end
function thread.holdFor(sec,n)
thread._Requests()
return yield(CMD, t_holdF, sec, n or dFunc)
@ -1744,6 +1831,10 @@ function multi.init(settings, realsettings)
else
multi.mainloop = mainloop
end
if settings.findopt then
find_optimization = true
multi.enableOptimization:Fire(multi, thread)
end
end
return _G["$multi"].multi,_G["$multi"].thread
end
@ -2093,5 +2184,64 @@ else
multi.m.sentinel = newproxy(true)
getmetatable(multi.m.sentinel).__gc = multi.m.onexit
end
local func_cache = {}
multi:newThread(function()
thread.skip()
if find_optimization then
function thread.hold(n,opt)
thread._Requests()
local opt = opt or {}
if type(opt)=="table" then
interval = opt.interval
if opt.cycles then
return yield(CMD, t_holdW, opt.cycles or 1, n or dFunc, interval)
elseif opt.sleep then
return yield(CMD, t_holdF, opt.sleep, n or dFunc, interval)
elseif opt.skip then
return yield(CMD, t_skip, opt.skip or 1, nil, interval)
end
end
if type(n) == "number" then
thread.getRunningThread().lastSleep = clock()
return yield(CMD, t_sleep, n or 0, nil, interval)
elseif type(n) == "table" and n.Type == "connector" then
local rdy = function()
return false
end
n(function(a1,a2,a3,a4,a5,a6)
rdy = function()
if a1==nil then
return NIL,a2,a3,a4,a5,a6
end
return a1,a2,a3,a4,a5,a6
end
end)
return yield(CMD, t_hold, function()
return rdy()
end, nil, interval)
elseif type(n) == "function" then
local cache = string.dump(n)
local f_str = tostring(n)
local good = true
for i=1,#func_cache do
if func_cache[i][1] == cache and func_cache[i][2] ~= f_str and not func_cache[i][3] then
multi:getOptimizationConnection():Fire("It's better to store a function to a variable than to use an anonymous function within the hold method!\n" .. debug.traceback())
func_cache[i][3] = true
good = false
end
end
if good then
table.insert(func_cache, {cache, f_str})
end
return yield(CMD, t_hold, n or dFunc, nil, interval)
else
error("Invalid argument passed to thread.hold(...)!")
end
end
-- Add more Overrides
end
end).OnError(print)
return multi

View File

@ -239,13 +239,14 @@ function multi:newSystemThreadedConnection(name)
thread:newThread("STC_SUB_MAN"..name,function()
local item
local sub_func = function() -- This will keep things held up until there is something to process
return c.subscribe:pop()
end
while true do
thread.yield()
-- We need to check on broken connections
ping(c) -- Should return instantlly and process this in another thread
item = thread.hold(function() -- This will keep things held up until there is something to process
return c.subscribe:pop()
end)
item = thread.hold(sub_func)
if item[1] == c.CONN then
multi.ForEach(c.links, function(link) -- Sync new connections
item[2]:push{c.CONN, link}

View File

@ -77,6 +77,7 @@ function multi:newSystemThread(name, func, ...)
c.creationTime = os.clock()
c.alive = true
c.priority = THREAD.Priority_Normal
local multi_settings = multi.defaultSettings
c.thread = lanes.gen("*",
{
globals={ -- Set up some globals
@ -88,6 +89,7 @@ function multi:newSystemThread(name, func, ...)
},
priority=c.priority
},function(...)
require("multi"):init(multi_settings)
require("multi.integration.lanesManager.extensions")
local has_error = true
return_linda:set("returns",{func(...)})

143
test.lua
View File

@ -1,8 +1,10 @@
package.path = "./?/init.lua;?.lua;lua5.4/share/lua/5.4/?/init.lua;lua5.4/share/lua/5.4/?.lua;"--..package.path
package.cpath = "lua5.4/lib/lua/5.4/?/core.dll;"--..package.cpath
multi, thread = require("multi"):init{print=true}
-- GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
multi:getOptimizationConnection()(function(msg)
print(msg)
end)
-- local conn1, conn2, conn3 = multi:newConnection(), multi:newConnection(), multi:newConnection()
-- thread:newThread(function()
-- print("Awaiting status")
@ -23,77 +25,74 @@ multi, thread = require("multi"):init{print=true}
-- conn3:Fire()
-- end)
local conn = multi:newSystemThreadedConnection("conn"):init()
multi:newSystemThread("Thread_Test_1", function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local console = THREAD.getConsole()
conn(function(a,b,c)
console.print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:mainloop()
end)
-- local conn = multi:newSystemThreadedConnection("conn"):init()
-- multi:newSystemThread("Thread_Test_1",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:mainloop()
-- end)
-- multi:newSystemThread("Thread_Test_2",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:newAlarm(2):OnRing(function()
-- console.print("Fire 2!!!")
-- conn:Fire(4,5,6)
-- THREAD.kill()
-- end)
-- multi:mainloop()
-- end)
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print("Mainloop conn got triggered!",a,b,c)
-- end)
-- alarm = multi:newAlarm(1)
-- alarm:OnRing(function()
-- console.print("Fire 1!!!")
-- conn:Fire(1,2,3)
-- end)
-- alarm = multi:newAlarm(3):OnRing(function()
-- multi:newSystemThread("Thread_Test_3",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:newAlarm(4):OnRing(function()
-- console.print("Fire 3!!!")
-- conn:Fire(7,8,9)
-- end)
-- multi:mainloop()
-- end)
-- end)
-- multi:newSystemThread("Thread_Test_4",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local conn2 = multi:newConnection()
-- local console = THREAD.getConsole()
-- multi:newAlarm(2):OnRing(function()
-- conn2:Fire()
-- end)
-- multi:newThread(function()
-- console.print("Conn Test!")
-- thread.hold(conn + conn2)
-- console.print("It held!")
-- end)
-- multi:mainloop()
-- end)
multi:newSystemThread("Thread_Test_2", function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local console = THREAD.getConsole()
conn(function(a,b,c)
console.print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(2):OnRing(function()
console.print("Fire 2!!!")
conn:Fire(4,5,6)
THREAD.kill()
end)
multi:mainloop()
end)
local console = THREAD.getConsole()
conn(function(a,b,c)
console.print("Mainloop conn got triggered!",a,b,c)
end)
alarm = multi:newAlarm(1)
alarm:OnRing(function()
console.print("Fire 1!!!")
conn:Fire(1,2,3)
end)
alarm = multi:newAlarm(3):OnRing(function()
multi:newSystemThread("Thread_Test_3",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local console = THREAD.getConsole()
conn(function(a,b,c)
console.print(THREAD:getName().." was triggered!",a,b,c)
end)
multi:newAlarm(4):OnRing(function()
console.print("Fire 3!!!")
conn:Fire(7,8,9)
end)
multi:mainloop()
end)
end)
multi:newSystemThread("Thread_Test_4",function()
local multi, thread = require("multi"):init()
local conn = GLOBAL["conn"]:init()
local conn2 = multi:newConnection()
local console = THREAD.getConsole()
multi:newAlarm(2):OnRing(function()
conn2:Fire()
end)
multi:newThread(function()
console.print("Conn Test!")
thread.hold(conn + conn2)
console.print("It held!")
end)
multi:mainloop()
end)
multi:mainloop()