aboutsummaryrefslogtreecommitdiff
path: root/tests/perftest.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tests/perftest.lua')
-rw-r--r--tests/perftest.lua184
1 files changed, 184 insertions, 0 deletions
diff --git a/tests/perftest.lua b/tests/perftest.lua
new file mode 100644
index 0000000..8ce1b3c
--- /dev/null
+++ b/tests/perftest.lua
@@ -0,0 +1,184 @@
1--
2-- PERFTEST.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3--
4-- Performance comparison of multithreaded Lua (= how much ballast does using
5-- Lua Lanes introduce)
6--
7-- Usage:
8-- [time] lua -lstrict perftest.lua [threads] [-plain|-single[=2..n]] [-time] [-prio[=-2..+2[,-2..+2]]]
9--
10-- threads: number of threads to launch (loops in 'plain' mode)
11-- -plain: runs in nonthreaded mode, to get a comparison baseline
12-- -single: runs using just a single CPU core (or 'n' cores if given)
13-- -prio: sets odd numbered threads to higher/lower priority
14--
15-- History:
16-- AKa 20-Jul-08: updated to Lanes 2008
17-- AK 14-Apr-07: works on Win32
18--
19-- To do:
20-- (none?)
21--
22
23-- On MSYS, stderr is buffered. In this test it matters.
24-- Seems, even with this MSYS wants to buffer linewise, needing '\n'
25-- before actual output.
26--
27local MSYS= os.getenv("OSTYPE")=="msys"
28
29
30require "lanes"
31
32local m= require "argtable"
33local argtable= assert( m.argtable )
34
35local N= 1000 -- threads/loops to use
36local M= 1000 -- sieves from 1..M
37local PLAIN= false -- single threaded (true) or using Lanes (false)
38local SINGLE= false -- cores to use (false / 1..n)
39local TIME= false -- use Lua for the timing
40local PRIO_ODD, PRIO_EVEN -- -3..+3
41
42local function HELP()
43 io.stderr:write( "Usage: lua perftest.lua [threads]\n" )
44end
45
46-- nil -> +2
47-- odd_prio[,even_prio]
48--
49local function prio_param(v)
50 if v==true then return 2,-2 end
51
52 local a,b= string.match( v, "^([%+%-]?%d+)%,([%+%-]?%d+)$" )
53 if a then
54 return tonumber(a), tonumber(b)
55 elseif tonumber(v) then
56 return tonumber(v)
57 else
58 error( "Bad priority: "..v )
59 end
60end
61
62for k,v in pairs( argtable(...) ) do
63 if k==1 then N= tonumber(v) or HELP()
64 elseif k=="plain" then PLAIN= true
65 elseif k=="single" then SINGLE= v -- true/number
66 elseif k=="time" then TIME= true
67 elseif k=="prio" then PRIO_ODD, PRIO_EVEN= prio_param(v)
68 else HELP()
69 end
70end
71
72PRIO_ODD= PRIO_ODD or 0
73PRIO_EVEN= PRIO_EVEN or 0
74
75
76-- SAMPLE ADOPTED FROM Lua 5.1.1 test/sieve.lua --
77
78-- the sieve of of Eratosthenes programmed with coroutines
79-- typical usage: lua -e N=1000 sieve.lua | column
80
81-- AK: Wrapped within a surrounding function, so we can pass it to Lanes
82-- Note that coroutines can perfectly fine be used within each Lane. :)
83--
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.
86--
87local function sieve_lane(N,id)
88
89 if MSYS then
90 io.stderr:setvbuf "no"
91 end
92
93 -- generate all the numbers from 2 to n
94 local function gen (n)
95 return coroutine.wrap(function ()
96 for i=2,n do coroutine.yield(i) end
97 end)
98 end
99
100 -- filter the numbers generated by `g', removing multiples of `p'
101 local function filter (p, g)
102 return coroutine.wrap(function ()
103 while 1 do
104 local n = g()
105 if n == nil then return end
106 if math.mod(n, p) ~= 0 then coroutine.yield(n) end
107 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
123 io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready
124
125 return ret
126end
127-- ** END OF LANE ** --
128
129
130-- Keep preparation code outside of the performance test
131--
132local f_even= lanes.gen( "base,coroutine,math,table,io", -- "*" = all
133 { priority= PRIO_EVEN }, sieve_lane )
134
135local f_odd= lanes.gen( "base,coroutine,math,table,io", -- "*" = all
136 { priority= PRIO_ODD }, sieve_lane )
137
138io.stderr:write( "*** Counting primes 1.."..M.." "..N.." times ***\n\n" )
139
140local t0= TIME and os.time()
141
142if PLAIN then
143 io.stderr:write( "Plain (no multithreading):\n" )
144
145 for i=1,N do
146 local tmp= sieve_lane(M,i)
147 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 )
148 end
149else
150 if SINGLE then
151 io.stderr:write( (tonumber(SINGLE) and SINGLE or 1) .. " core(s):\n" )
152 lanes.single(SINGLE) -- limit to N cores (just OS X)
153 else
154 io.stderr:write( "Multi core:\n" )
155 end
156
157 if PRIO_ODD ~= PRIO_EVEN then
158 io.stderr:write( ( PRIO_ODD > PRIO_EVEN and "ODD" or "EVEN" )..
159 " LANES should come first (odd:"..PRIO_ODD..", even:"..PRIO_EVEN..")\n\n" )
160 else
161 io.stderr:write( "EVEN AND ODD lanes should be mingled (both: "..PRIO_ODD..")\n\n" )
162 end
163 local t= {}
164 for i=1,N do
165 t[i]= ((i%2==0) and f_even or f_odd) (M,i)
166 end
167
168 -- Make sure all lanes finished
169 --
170 for i=1,N do
171 local tmp= t[i]:join()
172 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 )
173 end
174end
175
176io.stderr:write "\n"
177
178if TIME then
179 local t= os.time() - t0
180 io.stderr:write( "*** TIMING: "..t.." seconds ***\n" )
181end
182
183--
184-- end