aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/perftest.lua74
1 files 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
83-- 83--
84-- AKa 20-Jul-2008: Now the wrapping to one function is no longer needed; 84-- AKa 20-Jul-2008: Now the wrapping to one function is no longer needed;
85-- Lanes 2008 can take the used functions as upvalues. 85-- Lanes 2008 can take the used functions as upvalues.
86-- 86
87-- It looks like this implementation uses a lot of C stack, possibly resulting in stack overflow with Lua54
88-- this is reproducible with the original sieve.lua implementation found at https://www.lua.org/extras/
89-- for example:
90-- Lua54 exe built with 1Mb of C stack crashes for M above 230, C stack at 500 calls
91-- Lua53 exe built with 1Mb of C stack crashes for M above 491, C stack at 740 calls
92-- Lua52 exe built with 1Mb of C stack crashes for M above 672, C stack at 1000 calls
93-- Lua51 exe built with 1Mb of C stack crashes for M above 718, C stack at 900 calls
87local function sieve_lane(N,id) 94local function sieve_lane(N,id)
88 95
89 if MSYS then 96 if MSYS then
90 io.stderr:setvbuf "no" 97 io.stderr:setvbuf "no"
91 end 98 end
99
100 -- generate all the numbers from 2 to n
101 local function gen (n)
102 return coroutine.wrap(function ()
103 for i=2,n do coroutine.yield(i) end
104 end)
105 end
92 106
93 -- generate all the numbers from 2 to n 107 -- filter the numbers generated by `g', removing multiples of `p'
94 local function gen (n) 108 local function filter (p, g)
95 return coroutine.wrap(function () 109 return coroutine.wrap(function ()
96 for i=2,n do coroutine.yield(i) end 110 while 1 do
97 end) 111 local n = g()
98 end 112 if n == nil then return end
113 if math.fmod(n, p) ~= 0 then coroutine.yield(n) end
114 end
115 end)
116 end
99 117
100 -- filter the numbers generated by `g', removing multiples of `p' 118 local ret= {} -- returned values: { 2, 3, 5, 7, 11, ... }
101 local function filter (p, g) 119 N=N or 1000 -- from caller
102 return coroutine.wrap(function () 120 local x = gen(N) -- generate primes up to N
103 while 1 do 121 while 1 do
104 local n = g() 122 local n = x() -- pick a number until done
105 if n == nil then return end 123 if n == nil then break end
106 if math.fmod(n, p) ~= 0 then coroutine.yield(n) end 124 --print(n) -- must be a prime number
125 table.insert( ret, n )
126
127 x = filter(n, x) -- now remove its multiples
107 end 128 end
108 end)
109 end
110
111 local ret= {} -- returned values: { 2, 3, 5, 7, 11, ... }
112 N=N or 1000 -- from caller
113 local x = gen(N) -- generate primes up to N
114 while 1 do
115 local n = x() -- pick a number until done
116 if n == nil then break end
117 --print(n) -- must be a prime number
118 table.insert( ret, n )
119
120 x = filter(n, x) -- now remove its multiples
121 end
122 129
123 io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready 130 io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready
124 131
125 return ret 132 return ret
126end 133end
127-- ** END OF LANE ** -- 134-- ** END OF LANE ** --
128 135
@@ -169,6 +176,7 @@ else
169 -- 176 --
170 for i=1,N do 177 for i=1,N do
171 local tmp= t[i]:join() 178 local tmp= t[i]:join()
179 -- this assert will trigger if you change M to values below 1000 in order to solve C stack overflow
172 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 ) 180 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 )
173 end 181 end
174end 182end
@@ -180,5 +188,7 @@ if TIME then
180 io.stderr:write( "*** TIMING: "..t.." seconds ***\n" ) 188 io.stderr:write( "*** TIMING: "..t.." seconds ***\n" )
181end 189end
182 190
191io.stderr:write "done\n"
192
183-- 193--
184-- end 194-- end