-
Notifications
You must be signed in to change notification settings - Fork 1
/
tabLanes.lua
319 lines (268 loc) · 8.96 KB
/
tabLanes.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
--author cs
--email [email protected]
--https://github.com/ThinEureka/tabMachine
--multi-theading support with luaLanes(https://lualanes.github.io/lanes)
--your project should integrate luaLanes to use following code
--to use asyncRequireWithShareData, you also need to interate conf(https://github.com/cloudwu/lua-conf)
--created on Aug 26, 2021
-- With conf, you can share data between 2 lua states reducing the
-- overhead of cloning data.
g_t.asyncRequireWithShareData = function (modules)
return _({
s1 = function(c)
c._nickName = "asyncRequireWithShareData" .. #modules
local lanes = require("lanes")
local linda = lanes.linda()
c.linda = linda
local function load()
local index = 1
local sendNum = 0
local conf = require("conf")
while true do
local name = modules[index]
if name == nil then
break
end
local m= require(name)
local t = conf.host.new(m)
linda:send(0, "m", t)
index = index + 1
end
end
c.a = lanes.gen( "package", "table", load)()
c.index = 1
end,
s1_update = function(c)
local key, t = c.linda:receive(0, "m") -- timeout in seconds
if t == nil then
return
end
local box = conf.box(t)
package.loaded[modules[c.index]] = box
c.index = c.index + 1
if c.index >= #modules then
c:stop()
end
end,
})
end
-- Without conf, you need to disassemble big tables in the working thread
-- and reasseble them in the main thread to avoid blocking the main thread.
-- However, the total time can't be saved and you also need to pay for the
-- overhead of this mechanism.
local builderTable = class("builderTable")
function builderTable:ctor()
self._value = {}
end
function builderTable:append(key, value)
self._value[key] = value
end
function builderTable:complete()
return self._value
end
local function isEndCmd(k)
return k == "end"
end
local function isCmd(k)
return k == "table"
end
local builderMergeTable = class("builderMergeTable")
function builderMergeTable:ctor()
self._value = {}
end
function builderMergeTable:append(key, value)
for k, v in pairs(value) do
self._value[k] = v
end
end
function builderMergeTable:complete()
return self._value
end
g_t.tabReceiveStreamedTable = function (linda, frameTimeout)
frameTimeout = frameTimeout or 0
return _({
s1 = function(c)
-- c:s1_update()
c.receiveNum = 0
end,
s1_update = function(c)
local t1 = socket.gettime()
while true do
local p1 = socket.gettime()
local k, v = linda:receive(0, "m")
local p2 = socket.gettime()
if v == nil then
return
end
c.receiveNum = (c.receiveNum + 1) % 10
if c.lastBuilder ~= nil then
if not v.isEnd then
if v.cmd == nil then
c.lastBuilder:append(v.key, v.value)
else
local builder = c:_createBuilder(v.cmd)
builder.parentBuilder = c.lastBuilder
builder.parentKey = v.key
c.lastBuilder = builder
end
else
local value = c.lastBuilder:complete()
local key = c.lastBuilder.parentKey
c.lastBuilder = c.lastBuilder.parentBuilder
if c.lastBuilder ~= nil then
c.lastBuilder:append(key, value)
else
c:output(value)
c:stop()
return
end
end
else
if v.cmd == nil then
c:output(v.value)
c:stop()
return
end
c.lastBuilder = c:_createBuilder(v.cmd)
c.rootBuilder = c.lastBuilder
end
local t2 = socket.gettime()
if t2 - t1 > frameTimeout then
return
end
end
end,
--private:
_createBuilder = function(c, cmd)
if cmd == "table" then
return builderTable.new()
elseif cmd == "mergeTable" then
return builderMergeTable.new()
end
end,
})
end
g_t.asyncRequireByStep = function (modules, depth, frameTimeout)
return _({
s1 = function(c)
local lanes = require("lanes")
local linda = lanes.linda()
c.linda = linda
local function load()
local index = 1
local sendNum = 0
local m = {}
while true do
local name = modules[index]
if name == nil then
break
end
m[name] = require(name)
index = index + 1
end
local function sendTable(t, key, depth)
if depth ~= nil and depth <= 0 then
linda:send(0, "m", {key = key, value = t})
sendNum = (sendNum + 1) % 10
return
end
if depth ~= nil then
depth = depth - 1
end
linda:send(0, "m", {cmd = "table", key = key})
sendNum = (sendNum + 1) % 10
for k, v in pairs(t) do
if type(v) == "table" and (depth == nil or depth > 0) then
local newDepth = nil
if depth ~= nil then
newDepth = depth - 1
end
sendTable(v, k, newDepth)
else
linda:send(0, "m", {key=k, value = v})
sendNum = (sendNum + 1) % 10
end
end
linda:send(0, "m", {isEnd = true})
sendNum = (sendNum + 1) % 10
end
sendTable(m, nil, depth)
end
c.a = lanes.gen( "package", "table", load)()
c:call(g_t.tabReceiveStreamedTable(linda, frameTimeout), "s2", {"result"})
end,
})
end
g_t.asyncRequireFileOneByOne = function (modules, frameTimeout)
return g_t.asyncRequireByStep(modules, 2, frameTimeout)
end
g_t.asyncRequireBigFiles = function (modules, depth, maxLines)
return _({
s1 = function(c)
local lanes = require("lanes")
local linda = lanes.linda()
c.linda = linda
depth = 1
maxLines = maxLines or 100
c.t1 = socket.gettime()
local function load()
local index = 1
local sendNum = 0
local m = {}
while true do
local name = modules[index]
if name == nil then
break
end
m[name] = require(name)
index = index + 1
end
local sendTable
local sendMergeTable
sendMergeTable = function (t, key)
linda:send(nil, "m", {cmd = "mergeTable", key = key})
sendNum = (sendNum + 1) % 10
local unit = {}
local line = 0
for k, v in pairs(t) do
unit[k] = v
line = line + 1
if line >= maxLines then
linda:send(nil, "m", {value = unit})
sendNum = (sendNum + 1) % 10
line = 0
unit = {}
end
end
if line ~= 0 then
linda:send(nil, "m", {value = unit})
sendNum = (sendNum + 1) % 10
end
linda:send(nil, "m", {isEnd = true})
sendNum = (sendNum + 1) % 10
end
sendTable = function(t, key, curDepth)
linda:send(nil, "m", {cmd = "table", key = key})
sendNum = (sendNum + 1) % 10
for k, v in pairs(t) do
if type(v) == "table" then
if curDepth + 1 >= depth then
sendMergeTable(v, k)
else
sendTable(v, k, curDepth + 1)
end
else
linda:send(nil, "m", {key=k, value = v})
sendNum = (sendNum + 1) % 10
end
end
linda:send(nil, "m", {isEnd = true})
sendNum = (sendNum + 1) % 10
end
sendTable(m, nil, 0)
end
c.a = lanes.gen( "package", "table", load)()
c:call(g_t.tabReceiveStreamedTable(linda, 0), "s2", {"result"})
end,
})
end