diff options
author | Mark Pulford <mark@kyne.com.au> | 2012-01-13 22:11:17 +1030 |
---|---|---|
committer | Mark Pulford <mark@kyne.com.au> | 2012-03-04 18:54:34 +1030 |
commit | 46ba498b003b1ac4898b8db39c9aea5158af093f (patch) | |
tree | 369648eb4b2eaf3322719ac1dc9db7d091ca4581 /tests | |
parent | 3eee7e3db0ef209427f26be3099a0033deb86cb7 (diff) | |
download | lua-cjson-46ba498b003b1ac4898b8db39c9aea5158af093f.tar.gz lua-cjson-46ba498b003b1ac4898b8db39c9aea5158af093f.tar.bz2 lua-cjson-46ba498b003b1ac4898b8db39c9aea5158af093f.zip |
Improve benchmark stability
Update benchmark script to average the best half (round up) of the
result set. Ensure the initial call rate is calculated from a run of at
least 1ms.
Remove garbage collection control since any variations due to garbage
collection are better handled by averaging multiple results.
Diffstat (limited to 'tests')
-rwxr-xr-x | tests/bench.lua | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/tests/bench.lua b/tests/bench.lua index 0299ff2..cae4902 100755 --- a/tests/bench.lua +++ b/tests/bench.lua | |||
@@ -1,6 +1,7 @@ | |||
1 | #!/usr/bin/env lua | 1 | #!/usr/bin/env lua |
2 | 2 | ||
3 | -- Simple JSON benchmark. | 3 | -- This benchmark script measures wall clock time and should be |
4 | -- run on an unloaded system. | ||
4 | -- | 5 | -- |
5 | -- Your Mileage May Vary. | 6 | -- Your Mileage May Vary. |
6 | -- | 7 | -- |
@@ -25,24 +26,44 @@ end | |||
25 | local json_encode = find_func(json, { "encode", "Encode", "to_string", "stringify", "json" }) | 26 | local json_encode = find_func(json, { "encode", "Encode", "to_string", "stringify", "json" }) |
26 | local json_decode = find_func(json, { "decode", "Decode", "to_value", "parse" }) | 27 | local json_decode = find_func(json, { "decode", "Decode", "to_value", "parse" }) |
27 | 28 | ||
29 | local function average(t) | ||
30 | local total = 0 | ||
31 | for _, v in ipairs(t) do | ||
32 | total = total + v | ||
33 | end | ||
34 | return total / #t | ||
35 | end | ||
36 | |||
28 | function benchmark(tests, seconds, rep) | 37 | function benchmark(tests, seconds, rep) |
29 | local function bench(func, iter) | 38 | local function bench(func, iter) |
30 | -- collectgarbage("stop") | 39 | -- Use socket.gettime() to measure microsecond resolution |
31 | collectgarbage("collect") | 40 | -- wall clock time. |
32 | local t = socket.gettime() | 41 | local t = socket.gettime() |
33 | for i = 1, iter do | 42 | for i = 1, iter do |
34 | func(i) | 43 | func(i) |
35 | end | 44 | end |
36 | t = socket.gettime() - t | 45 | t = socket.gettime() - t |
37 | -- collectgarbage("restart") | 46 | |
47 | -- Don't trust any results when the run lasted for less than a | ||
48 | -- millisecond - return nil. | ||
49 | if t < 0.001 then | ||
50 | return nil | ||
51 | end | ||
52 | |||
38 | return (iter / t) | 53 | return (iter / t) |
39 | end | 54 | end |
40 | 55 | ||
41 | -- Roughly calculate the number of interations required | 56 | -- Roughly calculate the number of interations required |
42 | -- to obtain a particular time period. | 57 | -- to obtain a particular time period. |
43 | local function calc_iter(func, seconds) | 58 | local function calc_iter(func, seconds) |
44 | local base_iter = 10 | 59 | local iter = 1 |
45 | local rate = (bench(func, base_iter) + bench(func, base_iter)) / 2 | 60 | local rate |
61 | -- Warm up the bench function first. | ||
62 | func() | ||
63 | while not rate do | ||
64 | rate = bench(func, iter) | ||
65 | iter = iter * 10 | ||
66 | end | ||
46 | return math.ceil(seconds * rate) | 67 | return math.ceil(seconds * rate) |
47 | end | 68 | end |
48 | 69 | ||
@@ -55,13 +76,21 @@ function benchmark(tests, seconds, rep) | |||
55 | name = func | 76 | name = func |
56 | func = _G[name] | 77 | func = _G[name] |
57 | end | 78 | end |
79 | |||
58 | local iter = calc_iter(func, seconds) | 80 | local iter = calc_iter(func, seconds) |
81 | |||
59 | local result = {} | 82 | local result = {} |
60 | for i = 1, rep do | 83 | for i = 1, rep do |
61 | result[i] = bench(func, iter) | 84 | result[i] = bench(func, iter) |
62 | end | 85 | end |
86 | |||
87 | -- Remove the slowest half (round down) of the result set | ||
63 | table.sort(result) | 88 | table.sort(result) |
64 | test_results[name] = result[rep] | 89 | for i = 1, math.floor(#result / 2) do |
90 | table.remove(result, 1) | ||
91 | end | ||
92 | |||
93 | test_results[name] = average(result) | ||
65 | end | 94 | end |
66 | 95 | ||
67 | return test_results | 96 | return test_results |