1 |
|
2 |
|
3 |
|
4 | module.exports = bench
|
5 | bench.cpuSpeed = cpuSpeed
|
6 |
|
7 | function bench(tests, opts, next) {
|
8 | var i, test
|
9 | , keys = Object.keys(tests).reverse()
|
10 | , len = keys.length
|
11 | , times = []
|
12 | , samples = opts.samples || 7
|
13 | , warmupTime = 0|((opts.warmup || 2000)/len)
|
14 |
|
15 |
|
16 | for (i = len; i--; ) {
|
17 | test = tests[keys[i]]
|
18 | if (typeof test !== "function" && Array.isArray(test.fns)) {
|
19 | keys.splice.apply(keys, [i, 1].concat(test.fns.map(bindFn).reverse()))
|
20 | }
|
21 | len = keys.length
|
22 | }
|
23 | function bindFn(fn) {
|
24 | var name = keys[i] + "." + fn.name
|
25 | tests[name] = test.run.bind(test, fn)
|
26 | return name
|
27 | }
|
28 |
|
29 |
|
30 | for (i = len; i--; ) {
|
31 | measure(tests[keys[i]], warmupTime)
|
32 | times[i] = Array(samples)
|
33 | }
|
34 |
|
35 | i = len
|
36 |
|
37 | runSync()
|
38 |
|
39 | function runSync() {
|
40 | if (i-->0 || samples-->0 && (i = len - 1)) {
|
41 | times[i][samples] = measure(tests[keys[i]], opts["sample-time"] || 500)
|
42 | process.nextTick(runSync)
|
43 | } else {
|
44 | respond()
|
45 | }
|
46 | }
|
47 |
|
48 | function respond() {
|
49 | var diff, fastest, i, t
|
50 | , result = {}
|
51 | for (i = len; i--; ) {
|
52 | t = result[keys[i]] = stat(times[i])
|
53 | if (!fastest || t.ops > fastest) {
|
54 | fastest = t.ops
|
55 | }
|
56 | }
|
57 | for (i = len; (t = result[keys[--i]]); ) {
|
58 | diff = t.diff = Math.round((fastest - t.ops) / fastest * 100)
|
59 | t.rel = diff ? diff + "% slower" : "fastest"
|
60 | }
|
61 |
|
62 | if (typeof next === "function") {
|
63 | next(null, result)
|
64 | }
|
65 | }
|
66 | }
|
67 |
|
68 | function measure(fn, time) {
|
69 | var i, hr
|
70 | , count = 0
|
71 | , ms = 0
|
72 |
|
73 | if (global.gc) global.gc()
|
74 | for (; ms < time; ) {
|
75 | count++
|
76 | hr = process.hrtime()
|
77 | for (i = 1000; i--; ) fn()
|
78 | hr = process.hrtime(hr)
|
79 | ms += hr[0]*1e3 + hr[1]/1e6
|
80 | }
|
81 | return 1e6 * count / ms
|
82 | }
|
83 |
|
84 | function stat(arr) {
|
85 | var i, t
|
86 | , mean = 0
|
87 | , se = 0
|
88 | , len = arr.length
|
89 |
|
90 | for (i = len; i--; ) {
|
91 | mean += arr[i]
|
92 | }
|
93 | mean /= len
|
94 | for (i = len; i--; ) {
|
95 | t = arr[i] - mean
|
96 | se += t * t
|
97 | }
|
98 | se = ~~(1000 * (Math.sqrt(se / (len - 1)) / Math.sqrt(len)) / mean) / 10
|
99 | return {
|
100 | ops: mean|0,
|
101 | se: se,
|
102 | text: ((0|mean) + "").replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " ± " + se + "%"
|
103 | }
|
104 | }
|
105 |
|
106 | function cpuSpeed() {
|
107 | for (var i = 1e8, time = Date.now(); i--; );
|
108 | time = Date.now() - time
|
109 | return Math.round(1850 / time) / 10
|
110 | }
|
111 |
|