diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-06 10:22:29 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-06 10:22:29 +0200 |
| commit | a50367194b486e0abbe05aaee34b961e202635ba (patch) | |
| tree | 8e991e30e7508e45fb8edcb0b78f33b1227acbc4 | |
| parent | 4670b7deee3eeca20f72d91d9fb7094b51348956 (diff) | |
| download | lanes-a50367194b486e0abbe05aaee34b961e202635ba.tar.gz lanes-a50367194b486e0abbe05aaee34b961e202635ba.tar.bz2 lanes-a50367194b486e0abbe05aaee34b961e202635ba.zip | |
Fix Lua stack overflow in KeyUD:peek()
| -rw-r--r-- | src/keeper.cpp | 4 | ||||
| -rw-r--r-- | tests/linda_perf.lua | 161 |
2 files changed, 90 insertions, 75 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index e7574ed..d99cc50 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
| @@ -139,7 +139,9 @@ void KeyUD::peek(KeeperState const K_, int const count_) | |||
| 139 | // read <count_> value off the fifo | 139 | // read <count_> value off the fifo |
| 140 | prepareAccess(K_, -1); // K_: fifo | 140 | prepareAccess(K_, -1); // K_: fifo |
| 141 | int const _at{ lua_gettop(K_) }; | 141 | int const _at{ lua_gettop(K_) }; |
| 142 | for (int const _i : std::ranges::iota_view{ 1, std::min(count_, count) }) { // push val2 to valN | 142 | int const _count{ std::min(count_, count) }; |
| 143 | STACK_GROW(K_, _count); | ||
| 144 | for (int const _i : std::ranges::iota_view{ 1, _count }) { // push val2 to valN | ||
| 143 | lua_rawgeti(K_, 1, first + _i); // K_: fifo val2..N | 145 | lua_rawgeti(K_, 1, first + _i); // K_: fifo val2..N |
| 144 | } | 146 | } |
| 145 | lua_rawgeti(K_, 1, first); // push val1 // K_: fifo val2..N val1 | 147 | lua_rawgeti(K_, 1, first); // push val1 // K_: fifo val2..N val1 |
diff --git a/tests/linda_perf.lua b/tests/linda_perf.lua index b173d12..8fa8242 100644 --- a/tests/linda_perf.lua +++ b/tests/linda_perf.lua | |||
| @@ -18,6 +18,30 @@ local finalizer = function(err, stk) | |||
| 18 | end | 18 | end |
| 19 | 19 | ||
| 20 | -- ################################################################################################# | 20 | -- ################################################################################################# |
| 21 | if false then | ||
| 22 | do | ||
| 23 | print "############################################ tests get/set" | ||
| 24 | -- linda:get throughput | ||
| 25 | local l = lanes.linda("get/set") | ||
| 26 | local batch = {} | ||
| 27 | for i = 1,1000 do | ||
| 28 | table.insert(batch, i) | ||
| 29 | end | ||
| 30 | for _,size in ipairs{1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 } do | ||
| 31 | l:set("<->", table_unpack(batch)) | ||
| 32 | local count = math.floor(20000000/size) | ||
| 33 | print("START", "get("..size..") " .. count, " times") | ||
| 34 | local t1 = lanes.now_secs() | ||
| 35 | for i = 1, 2000000/math.sqrt(size) do | ||
| 36 | l:get("<->", size) | ||
| 37 | end | ||
| 38 | print("DURATION = " .. lanes.now_secs() - t1 .. "\n") | ||
| 39 | end | ||
| 40 | end | ||
| 41 | collectgarbage() | ||
| 42 | end | ||
| 43 | |||
| 44 | -- ################################################################################################# | ||
| 21 | 45 | ||
| 22 | -- this lane eats items in the linda one by one | 46 | -- this lane eats items in the linda one by one |
| 23 | local eater = function( l, loop) | 47 | local eater = function( l, loop) |
| @@ -59,10 +83,10 @@ local lane_gobbler_gen = lanes.gen( "*", {priority = 3}, gobbler) | |||
| 59 | -- ################################################################################################# | 83 | -- ################################################################################################# |
| 60 | 84 | ||
| 61 | -- main thread writes data while a lane reads it | 85 | -- main thread writes data while a lane reads it |
| 62 | local function ziva( preloop, loop, batch) | 86 | local function ziva1( preloop, loop, batch) |
| 63 | -- prefill the linda a bit to increase fifo stress | 87 | -- prefill the linda a bit to increase fifo stress |
| 64 | local top = math.max( preloop, loop) | 88 | local top = math.max( preloop, loop) |
| 65 | local l = lanes.linda() | 89 | local l = lanes.linda("ziva1("..preloop..":"..loop..":"..batch..")") |
| 66 | local t1 = lanes.now_secs() | 90 | local t1 = lanes.now_secs() |
| 67 | for i = 1, preloop do | 91 | for i = 1, preloop do |
| 68 | l:send( "key", i) | 92 | l:send( "key", i) |
| @@ -104,60 +128,44 @@ local function ziva( preloop, loop, batch) | |||
| 104 | end | 128 | end |
| 105 | 129 | ||
| 106 | -- ################################################################################################# | 130 | -- ################################################################################################# |
| 107 | do | 131 | |
| 108 | print "############################################ tests get/set" | 132 | if true then |
| 109 | -- linda:get throughput | 133 | do |
| 110 | local l = lanes.linda("get/set") | 134 | TEST1 = TEST1 or 1000 |
| 111 | local batch = {} | 135 | PREFILL1 = PREFILL1 or 10000 |
| 112 | for i = 1,1000 do | 136 | FILL1 = FILL1 or 2000000 |
| 113 | table.insert(batch, i) | 137 | |
| 114 | end | 138 | local tests1 = |
| 115 | for _,size in ipairs{1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 } do | 139 | { |
| 116 | l:set("<->", table_unpack(batch)) | 140 | { PREFILL1, FILL1, 0}, |
| 117 | local count = 20000000//size | 141 | { PREFILL1, FILL1, 1}, |
| 118 | print("START", "get("..size..") " .. count, " times") | 142 | { PREFILL1, FILL1, 2}, |
| 119 | local t1 = lanes.now_secs() | 143 | { PREFILL1, FILL1, 3}, |
| 120 | for i = 1, 2000000/math.sqrt(size) do | 144 | { PREFILL1, FILL1, 5}, |
| 121 | l:get("<->", size) | 145 | { PREFILL1, FILL1, 8}, |
| 146 | { PREFILL1, FILL1, 13}, | ||
| 147 | { PREFILL1, FILL1, 21}, | ||
| 148 | { PREFILL1, FILL1, 34}, | ||
| 149 | { PREFILL1, FILL1, 55}, | ||
| 150 | { PREFILL1, FILL1, 89}, | ||
| 151 | } | ||
| 152 | print "############################################ tests #1" | ||
| 153 | for i, v in ipairs( tests1) do | ||
| 154 | if i > TEST1 then break end | ||
| 155 | local pre, loop, batch = v[1], v[2], v[3] | ||
| 156 | print("-------------------------------------------------\n") | ||
| 157 | print("START", "prefill="..pre, "fill="..loop, "batch="..batch) | ||
| 158 | print("DURATION = " .. ziva1( pre, loop, batch) .. "\n") | ||
| 122 | end | 159 | end |
| 123 | print("DURATION = " .. lanes.now_secs() - t1 .. "\n") | ||
| 124 | end | 160 | end |
| 125 | end | 161 | collectgarbage() |
| 126 | |||
| 127 | -- ################################################################################################# | ||
| 128 | |||
| 129 | TEST1 = TEST1 or 1000 | ||
| 130 | PREFILL1 = PREFILL1 or 10000 | ||
| 131 | FILL1 = FILL1 or 2000000 | ||
| 132 | |||
| 133 | local tests1 = | ||
| 134 | { | ||
| 135 | { PREFILL1, FILL1, 0}, | ||
| 136 | { PREFILL1, FILL1, 1}, | ||
| 137 | { PREFILL1, FILL1, 2}, | ||
| 138 | { PREFILL1, FILL1, 3}, | ||
| 139 | { PREFILL1, FILL1, 5}, | ||
| 140 | { PREFILL1, FILL1, 8}, | ||
| 141 | { PREFILL1, FILL1, 13}, | ||
| 142 | { PREFILL1, FILL1, 21}, | ||
| 143 | { PREFILL1, FILL1, 34}, | ||
| 144 | { PREFILL1, FILL1, 55}, | ||
| 145 | { PREFILL1, FILL1, 89}, | ||
| 146 | } | ||
| 147 | print "############################################ tests #1" | ||
| 148 | for i, v in ipairs( tests1) do | ||
| 149 | if i > TEST1 then break end | ||
| 150 | local pre, loop, batch = v[1], v[2], v[3] | ||
| 151 | print("-------------------------------------------------\n") | ||
| 152 | print("START", "prefill="..pre, "fill="..loop, "batch="..batch) | ||
| 153 | print("DURATION = " .. ziva( pre, loop, batch) .. "\n") | ||
| 154 | end | 162 | end |
| 155 | 163 | ||
| 156 | -- ################################################################################################# | 164 | -- ################################################################################################# |
| 157 | 165 | ||
| 158 | -- sequential write/read (no parallelization involved) | 166 | -- sequential write/read (no parallelization involved) |
| 159 | local function ziva2( preloop, loop, batch) | 167 | local function ziva2( preloop, loop, batch) |
| 160 | local l = lanes.linda() | 168 | local l = lanes.linda("ziva2("..preloop..":"..loop..":"..tostring(batch)..")") |
| 161 | -- prefill the linda a bit to increase fifo stress | 169 | -- prefill the linda a bit to increase fifo stress |
| 162 | local top, step = math.max( preloop, loop), (l.batched and batch) and batch or 1 | 170 | local top, step = math.max( preloop, loop), (l.batched and batch) and batch or 1 |
| 163 | local batch_send, batch_read | 171 | local batch_send, batch_read |
| @@ -203,32 +211,37 @@ end | |||
| 203 | 211 | ||
| 204 | -- ################################################################################################# | 212 | -- ################################################################################################# |
| 205 | 213 | ||
| 206 | TEST2 = TEST2 or 1000 | 214 | if true then |
| 207 | PREFILL2 = PREFILL2 or 0 | 215 | do |
| 208 | FILL2 = FILL2 or 4000000 | 216 | TEST2 = TEST2 or 1000 |
| 209 | 217 | PREFILL2 = PREFILL2 or 0 | |
| 210 | local tests2 = | 218 | FILL2 = FILL2 or 4000000 |
| 211 | { | 219 | |
| 212 | { PREFILL2, FILL2}, | 220 | local tests2 = |
| 213 | { PREFILL2, FILL2, 1}, | 221 | { |
| 214 | { PREFILL2, FILL2, 2}, | 222 | { PREFILL2, FILL2}, |
| 215 | { PREFILL2, FILL2, 3}, | 223 | { PREFILL2, FILL2, 1}, |
| 216 | { PREFILL2, FILL2, 5}, | 224 | { PREFILL2, FILL2, 2}, |
| 217 | { PREFILL2, FILL2, 8}, | 225 | { PREFILL2, FILL2, 3}, |
| 218 | { PREFILL2, FILL2, 13}, | 226 | { PREFILL2, FILL2, 5}, |
| 219 | { PREFILL2, FILL2, 21}, | 227 | { PREFILL2, FILL2, 8}, |
| 220 | { PREFILL2, FILL2, 34}, | 228 | { PREFILL2, FILL2, 13}, |
| 221 | { PREFILL2, FILL2, 55}, | 229 | { PREFILL2, FILL2, 21}, |
| 222 | { PREFILL2, FILL2, 89}, | 230 | { PREFILL2, FILL2, 34}, |
| 223 | } | 231 | { PREFILL2, FILL2, 55}, |
| 224 | 232 | { PREFILL2, FILL2, 89}, | |
| 225 | print "############################################ tests #2" | 233 | } |
| 226 | for i, v in ipairs( tests2) do | 234 | |
| 227 | if i > TEST2 then break end | 235 | print "############################################ tests #2" |
| 228 | local pre, loop, batch = v[1], v[2], v[3] | 236 | for i, v in ipairs( tests2) do |
| 229 | print("-------------------------------------------------\n") | 237 | if i > TEST2 then break end |
| 230 | print("START", "prefill="..pre, "fill="..loop, "batch="..(batch or "no")) | 238 | local pre, loop, batch = v[1], v[2], v[3] |
| 231 | print("DURATION = " .. ziva2( pre, loop, batch) .. "\n") | 239 | print("-------------------------------------------------\n") |
| 240 | print("START", "prefill="..pre, "fill="..loop, "batch="..(batch or "no")) | ||
| 241 | print("DURATION = " .. ziva2( pre, loop, batch) .. "\n") | ||
| 242 | end | ||
| 243 | end | ||
| 244 | collectgarbage() | ||
| 232 | end | 245 | end |
| 233 | 246 | ||
| 234 | print "############################################" | 247 | print "############################################" |
