diff options
-rw-r--r-- | tests/perftest.lua | 74 |
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 | ||
87 | local function sieve_lane(N,id) | 94 | local 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 |
126 | end | 133 | end |
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 |
174 | end | 182 | end |
@@ -180,5 +188,7 @@ if TIME then | |||
180 | io.stderr:write( "*** TIMING: "..t.." seconds ***\n" ) | 188 | io.stderr:write( "*** TIMING: "..t.." seconds ***\n" ) |
181 | end | 189 | end |
182 | 190 | ||
191 | io.stderr:write "done\n" | ||
192 | |||
183 | -- | 193 | -- |
184 | -- end | 194 | -- end |