bench.lua 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #!/usr/bin/env lua
  2. -- This benchmark script measures wall clock time and should be
  3. -- run on an unloaded system.
  4. --
  5. -- Your Mileage May Vary.
  6. --
  7. -- Mark Pulford <mark@kyne.com.au>
  8. local json_module = os.getenv("JSON_MODULE") or "cjson"
  9. require "socket"
  10. local json = require(json_module)
  11. local util = require "cjson.util"
  12. local function find_func(mod, funcnames)
  13. for _, v in ipairs(funcnames) do
  14. if mod[v] then
  15. return mod[v]
  16. end
  17. end
  18. return nil
  19. end
  20. local json_encode = find_func(json, { "encode", "Encode", "to_string", "stringify", "json" })
  21. local json_decode = find_func(json, { "decode", "Decode", "to_value", "parse" })
  22. local function average(t)
  23. local total = 0
  24. for _, v in ipairs(t) do
  25. total = total + v
  26. end
  27. return total / #t
  28. end
  29. function benchmark(tests, seconds, rep)
  30. local function bench(func, iter)
  31. -- Use socket.gettime() to measure microsecond resolution
  32. -- wall clock time.
  33. local t = socket.gettime()
  34. for i = 1, iter do
  35. func(i)
  36. end
  37. t = socket.gettime() - t
  38. -- Don't trust any results when the run lasted for less than a
  39. -- millisecond - return nil.
  40. if t < 0.001 then
  41. return nil
  42. end
  43. return (iter / t)
  44. end
  45. -- Roughly calculate the number of interations required
  46. -- to obtain a particular time period.
  47. local function calc_iter(func, seconds)
  48. local iter = 1
  49. local rate
  50. -- Warm up the bench function first.
  51. func()
  52. while not rate do
  53. rate = bench(func, iter)
  54. iter = iter * 10
  55. end
  56. return math.ceil(seconds * rate)
  57. end
  58. local test_results = {}
  59. for name, func in pairs(tests) do
  60. -- k(number), v(string)
  61. -- k(string), v(function)
  62. -- k(number), v(function)
  63. if type(func) == "string" then
  64. name = func
  65. func = _G[name]
  66. end
  67. local iter = calc_iter(func, seconds)
  68. local result = {}
  69. for i = 1, rep do
  70. result[i] = bench(func, iter)
  71. end
  72. -- Remove the slowest half (round down) of the result set
  73. table.sort(result)
  74. for i = 1, math.floor(#result / 2) do
  75. table.remove(result, 1)
  76. end
  77. test_results[name] = average(result)
  78. end
  79. return test_results
  80. end
  81. function bench_file(filename)
  82. local data_json = util.file_load(filename)
  83. local data_obj = json_decode(data_json)
  84. local function test_encode()
  85. json_encode(data_obj)
  86. end
  87. local function test_decode()
  88. json_decode(data_json)
  89. end
  90. local tests = {}
  91. if json_encode then tests.encode = test_encode end
  92. if json_decode then tests.decode = test_decode end
  93. return benchmark(tests, 0.1, 5)
  94. end
  95. -- Optionally load any custom configuration required for this module
  96. local success, data = pcall(util.file_load, ("bench-%s.lua"):format(json_module))
  97. if success then
  98. util.run_script(data, _G)
  99. configure(json)
  100. end
  101. for i = 1, #arg do
  102. local results = bench_file(arg[i])
  103. for k, v in pairs(results) do
  104. print(("%s\t%s\t%d"):format(arg[i], k, v))
  105. end
  106. end
  107. -- vi:ai et sw=4 ts=4: