From caf556e2dcb3df4992dd386a2b37535df42fc880 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Wed, 27 Mar 2024 17:02:37 +0100 Subject: updated perftest.lua --- tests/perftest.lua | 74 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/tests/perftest.lua b/tests/perftest.lua index 6ffc064..35f522c 100644 --- a/tests/perftest.lua +++ b/tests/perftest.lua @@ -83,46 +83,53 @@ PRIO_EVEN= PRIO_EVEN or 0 -- -- AKa 20-Jul-2008: Now the wrapping to one function is no longer needed; -- Lanes 2008 can take the used functions as upvalues. --- + +-- It looks like this implementation uses a lot of C stack, possibly resulting in stack overflow with Lua54 +-- this is reproducible with the original sieve.lua implementation found at https://www.lua.org/extras/ +-- for example: +-- Lua54 exe built with 1Mb of C stack crashes for M above 230, C stack at 500 calls +-- Lua53 exe built with 1Mb of C stack crashes for M above 491, C stack at 740 calls +-- Lua52 exe built with 1Mb of C stack crashes for M above 672, C stack at 1000 calls +-- Lua51 exe built with 1Mb of C stack crashes for M above 718, C stack at 900 calls local function sieve_lane(N,id) - if MSYS then - io.stderr:setvbuf "no" - end + if MSYS then + io.stderr:setvbuf "no" + end + + -- generate all the numbers from 2 to n + local function gen (n) + return coroutine.wrap(function () + for i=2,n do coroutine.yield(i) end + end) + end - -- generate all the numbers from 2 to n - local function gen (n) - return coroutine.wrap(function () - for i=2,n do coroutine.yield(i) end - end) - end + -- filter the numbers generated by `g', removing multiples of `p' + local function filter (p, g) + return coroutine.wrap(function () + while 1 do + local n = g() + if n == nil then return end + if math.fmod(n, p) ~= 0 then coroutine.yield(n) end + end + end) + end - -- filter the numbers generated by `g', removing multiples of `p' - local function filter (p, g) - return coroutine.wrap(function () + local ret= {} -- returned values: { 2, 3, 5, 7, 11, ... } + N=N or 1000 -- from caller + local x = gen(N) -- generate primes up to N while 1 do - local n = g() - if n == nil then return end - if math.fmod(n, p) ~= 0 then coroutine.yield(n) end + local n = x() -- pick a number until done + if n == nil then break end + --print(n) -- must be a prime number + table.insert( ret, n ) + + x = filter(n, x) -- now remove its multiples end - end) - end - - local ret= {} -- returned values: { 2, 3, 5, 7, 11, ... } - N=N or 1000 -- from caller - local x = gen(N) -- generate primes up to N - while 1 do - local n = x() -- pick a number until done - if n == nil then break end - --print(n) -- must be a prime number - table.insert( ret, n ) - - x = filter(n, x) -- now remove its multiples - end - io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready + io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready - return ret + return ret end -- ** END OF LANE ** -- @@ -169,6 +176,7 @@ else -- for i=1,N do local tmp= t[i]:join() + -- this assert will trigger if you change M to values below 1000 in order to solve C stack overflow assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 ) end end @@ -180,5 +188,7 @@ if TIME then io.stderr:write( "*** TIMING: "..t.." seconds ***\n" ) end +io.stderr:write "done\n" + -- -- end -- cgit v1.2.3-55-g6feb