codemix/fast.js — pull request #46 by phpnode (2014-07-01 00:22:20+00:00)
Title: Better benchmarks

After a brief conversation with @mraleph on twitter, I've made some changes to the benchmarks to ensure that we're not only measuring monomophic behaviour. This PR adds a `utils.fns()` helper which accepts the same arguments as the function constructor. It creates 20 individiual copies of the same function, then returns a function which will endlessly return one of those functions when called. We then use this in place of the previous function definitions in our benchmarks.

This does not seem to have a significant impact on performance.

#### V8
```
Running 41 benchmarks, please wait...

Native try {} catch (e) {} vs fast.try()
✓ try...catch x 105,466 ops/sec ±2.06% (87 runs sampled)
✓ fast.try() x 2,651,775 ops/sec ±1.48% (96 runs sampled)

Result: fast.js is 2414.33% faster than try...catch.

Native try {} catch (e) {} vs fast.try() (single function call)
✓ try...catch x 99,293 ops/sec ±2.23% (83 runs sampled)
✓ fast.try() x 2,748,030 ops/sec ±1.56% (88 runs sampled)

Result: fast.js is 2667.60% faster than try...catch.

Native .apply() vs fast.apply() (3 items, no context)
✓ Function::apply() x 16,785,063 ops/sec ±1.78% (94 runs sampled)
✓ fast.apply() x 25,583,853 ops/sec ±1.95% (86 runs sampled)

Result: fast.js is 52.42% faster than Function::apply().

Native .apply() vs fast.apply() (3 items, with context)
✓ Function::apply() x 14,999,597 ops/sec ±2.07% (86 runs sampled)
✓ fast.apply() x 19,870,643 ops/sec ±2.24% (82 runs sampled)

Result: fast.js is 32.47% faster than Function::apply().

Native .apply() vs fast.apply() (6 items, no context)
✓ Function::apply() x 17,521,387 ops/sec ±2.21% (92 runs sampled)
✓ fast.apply() x 25,153,304 ops/sec ±1.79% (91 runs sampled)

Result: fast.js is 43.56% faster than Function::apply().

Native .apply() vs fast.apply() (6 items, with context)
✓ Function::apply() x 13,669,451 ops/sec ±1.81% (90 runs sampled)
✓ fast.apply() x 17,976,972 ops/sec ±1.67% (84 runs sampled)

Result: fast.js is 31.51% faster than Function::apply().

Native .apply() vs fast.apply() (10 items, no context)
✓ Function::apply() x 11,534,185 ops/sec ±2.20% (79 runs sampled)
✓ fast.apply() x 10,928,640 ops/sec ±1.82% (91 runs sampled)

Result: fast.js is 5.25% slower than Function::apply().

Native .apply() vs fast.apply() (10 items, with context)
✓ Function::apply() x 11,732,785 ops/sec ±2.01% (85 runs sampled)
✓ fast.apply() x 9,237,870 ops/sec ±2.19% (83 runs sampled)

Result: fast.js is 21.26% slower than Function::apply().

fast.clone() vs underscore.clone() vs lodash.clone()
✓ fast.clone() x 920,402 ops/sec ±2.31% (87 runs sampled)
✓ underscore.clone() x 603,135 ops/sec ±2.38% (84 runs sampled)
✓ lodash.clone() x 410,177 ops/sec ±2.07% (89 runs sampled)

Result: fast.js is 124.39% faster than lodash.clone().

Native .indexOf() vs fast.indexOf() (3 items)
✓ Array::indexOf() x 16,983,868 ops/sec ±1.83% (91 runs sampled)
✓ fast.indexOf() x 21,049,160 ops/sec ±2.20% (88 runs sampled)
✓ fast.indexOf() v0.0.2 x 27,126,158 ops/sec ±1.94% (90 runs sampled)
✓ underscore.indexOf() x 12,781,513 ops/sec ±2.63% (92 runs sampled)
✓ lodash.indexOf() x 18,326,694 ops/sec ±1.81% (90 runs sampled)

Result: fast.js is 23.94% faster than Array::indexOf().

Native .indexOf() vs fast.indexOf() (10 items)
✓ Array::indexOf() x 12,256,282 ops/sec ±2.10% (81 runs sampled)
✓ fast.indexOf() x 15,169,565 ops/sec ±2.57% (82 runs sampled)
✓ fast.indexOf() v0.0.2 x 17,622,516 ops/sec ±2.31% (83 runs sampled)
✓ underscore.indexOf() x 9,312,207 ops/sec ±2.30% (86 runs sampled)
✓ lodash.indexOf() x 12,966,716 ops/sec ±1.83% (85 runs sampled)

Result: fast.js is 23.77% faster than Array::indexOf().

Native .indexOf() vs fast.indexOf() (1000 items)
✓ Array::indexOf() x 357,917 ops/sec ±1.80% (93 runs sampled)
✓ fast.indexOf() x 356,890 ops/sec ±2.12% (85 runs sampled)
✓ fast.indexOf() v0.0.2 x 372,588 ops/sec ±1.60% (92 runs sampled)
✓ underscore.indexOf() x 335,526 ops/sec ±1.84% (82 runs sampled)
✓ lodash.indexOf() x 321,777 ops/sec ±2.05% (90 runs sampled)

Result: fast.js is 0.29% slower than Array::indexOf().

Native .lastIndexOf() vs fast.lastIndexOf() (3 items)
✓ Array::lastIndexOf() x 30,527,782 ops/sec ±2.24% (83 runs sampled)
✓ fast.lastIndexOf() x 38,490,043 ops/sec ±2.00% (85 runs sampled)
✓ fast.lastIndexOf() v0.0.2 x 48,480,313 ops/sec ±1.88% (76 runs sampled)
✓ underscore.lastIndexOf() x 22,393,968 ops/sec ±1.81% (93 runs sampled)
✓ lodash.lastIndexOf() x 37,265,123 ops/sec ±1.58% (83 runs sampled)

Result: fast.js is 26.08% faster than Array::lastIndexOf().

Native .lastIndexOf() vs fast.lastIndexOf() (10 items)
✓ Array::lastIndexOf() x 16,584,685 ops/sec ±2.28% (83 runs sampled)
✓ fast.lastIndexOf() x 22,734,469 ops/sec ±2.25% (89 runs sampled)
✓ fast.lastIndexOf() v0.0.2 x 29,066,070 ops/sec ±1.62% (90 runs sampled)
✓ underscore.lastIndexOf() x 11,128,156 ops/sec ±2.64% (84 runs sampled)
✓ lodash.lastIndexOf() x 21,832,150 ops/sec ±2.23% (88 runs sampled)

Result: fast.js is 37.08% faster than Array::lastIndexOf().

Native .lastIndexOf() vs fast.lastIndexOf() (1000 items)
✓ Array::lastIndexOf() x 806,403 ops/sec ±1.58% (95 runs sampled)
✓ fast.lastIndexOf() x 927,539 ops/sec ±1.58% (91 runs sampled)
✓ fast.lastIndexOf() v0.0.2 x 949,969 ops/sec ±1.66% (92 runs sampled)
✓ underscore.lastIndexOf() x 794,580 ops/sec ±1.69% (92 runs sampled)
✓ lodash.lastIndexOf() x 822,500 ops/sec ±1.76% (90 runs sampled)

Result: fast.js is 15.02% faster than Array::lastIndexOf().

Native .bind() vs fast.bind()
✓ Function::bind() x 859,813 ops/sec ±2.05% (83 runs sampled)
✓ fast.bind() x 6,105,845 ops/sec ±2.16% (83 runs sampled)
✓ underscore.bind() x 529,154 ops/sec ±2.63% (80 runs sampled)
✓ lodash.bind() x 340,215 ops/sec ±2.12% (87 runs sampled)

Result: fast.js is 610.14% faster than Function::bind().

Native .bind() vs fast.bind() with prebound functions
✓ Function::bind() x 4,676,885 ops/sec ±1.98% (91 runs sampled)
✓ fast.bind() x 14,287,252 ops/sec ±2.32% (85 runs sampled)
✓ underscore.bind() x 4,752,183 ops/sec ±1.60% (84 runs sampled)
✓ lodash.bind() x 4,979,719 ops/sec ±1.58% (91 runs sampled)

Result: fast.js is 205.49% faster than Function::bind().

Native .bind() vs fast.partial()
✓ Function::bind() x 860,646 ops/sec ±2.64% (78 runs sampled)
✓ fast.partial() x 7,254,496 ops/sec ±2.14% (87 runs sampled)
✓ fast.partial() v0.0.0 x 7,220,151 ops/sec ±1.50% (88 runs sampled)
✓ underscore.partial() x 1,555,508 ops/sec ±1.97% (87 runs sampled)
✓ lodash.partial() x 324,217 ops/sec ±1.89% (89 runs sampled)

Result: fast.js is 742.91% faster than Function::bind().

Native .bind() vs fast.partial() with prebound functions
✓ Function::bind() x 4,444,169 ops/sec ±1.88% (91 runs sampled)
✓ fast.partial() x 14,430,005 ops/sec ±2.06% (89 runs sampled)
✓ fast.partial() v0.0.0 x 14,931,778 ops/sec ±2.07% (92 runs sampled)
✓ underscore.partial() x 6,557,918 ops/sec ±2.81% (81 runs sampled)
✓ lodash.partial() x 4,723,433 ops/sec ±1.97% (92 runs sampled)

Result: fast.js is 224.70% faster than Function::bind().

Native .map() vs fast.map() (3 items)
✓ Array::map() x 1,942,305 ops/sec ±2.25% (78 runs sampled)
✓ fast.map() x 10,561,264 ops/sec ±1.87% (89 runs sampled)
✓ fast.map() v0.0.2a x 9,779,384 ops/sec ±2.09% (90 runs sampled)
✓ fast.map() v0.0.1 x 9,708,728 ops/sec ±1.75% (93 runs sampled)
✓ fast.map() v0.0.0 x 9,618,138 ops/sec ±1.86% (94 runs sampled)
✓ underscore.map() x 1,702,525 ops/sec ±1.75% (72 runs sampled)
✓ lodash.map() x 7,019,259 ops/sec ±1.86% (90 runs sampled)

Result: fast.js is 443.75% faster than Array::map().

Native .map() vs fast.map() (10 items)
✓ Array::map() x 1,237,255 ops/sec ±1.70% (77 runs sampled)
✓ fast.map() x 4,480,418 ops/sec ±1.95% (89 runs sampled)
✓ fast.map() v0.0.2a x 4,338,708 ops/sec ±1.94% (91 runs sampled)
✓ fast.map() v0.0.1 x 4,283,168 ops/sec ±1.99% (86 runs sampled)
✓ fast.map() v0.0.0 x 3,882,834 ops/sec ±1.82% (94 runs sampled)
✓ underscore.map() x 1,163,540 ops/sec ±1.93% (77 runs sampled)
✓ lodash.map() x 3,461,079 ops/sec ±2.08% (90 runs sampled)

Result: fast.js is 262.13% faster than Array::map().

Native .map() vs fast.map() (1000 items)
✓ Array::map() x 26,145 ops/sec ±2.32% (90 runs sampled)
✓ fast.map() x 55,563 ops/sec ±2.02% (86 runs sampled)
✓ fast.map() v0.0.2a x 57,234 ops/sec ±1.73% (89 runs sampled)
✓ fast.map() v0.0.1 x 58,266 ops/sec ±2.10% (90 runs sampled)
✓ fast.map() v0.0.0 x 46,972 ops/sec ±2.07% (93 runs sampled)
✓ underscore.map() x 26,619 ops/sec ±2.18% (92 runs sampled)
✓ lodash.map() x 50,548 ops/sec ±1.80% (86 runs sampled)

Result: fast.js is 112.52% faster than Array::map().

Native .filter() vs fast.filter() (3 items)
✓ Array::filter() x 1,754,228 ops/sec ±2.37% (79 runs sampled)
✓ fast.filter() x 6,402,097 ops/sec ±1.82% (92 runs sampled)
✓ underscore.filter() x 1,569,185 ops/sec ±2.40% (80 runs sampled)
✓ lodash.filter() x 4,716,871 ops/sec ±2.36% (85 runs sampled)

Result: fast.js is 264.95% faster than Array::filter().

Native .filter() vs fast.filter() (10 items)
✓ Array::filter() x 907,935 ops/sec ±2.19% (86 runs sampled)
✓ fast.filter() x 2,727,907 ops/sec ±1.97% (93 runs sampled)
✓ underscore.filter() x 864,985 ops/sec ±2.40% (72 runs sampled)
✓ lodash.filter() x 2,491,784 ops/sec ±1.86% (87 runs sampled)

Result: fast.js is 200.45% faster than Array::filter().

Native .filter() vs fast.filter() (1000 items)
✓ Array::filter() x 18,519 ops/sec ±2.13% (87 runs sampled)
✓ fast.filter() x 31,714 ops/sec ±1.74% (90 runs sampled)
✓ underscore.filter() x 18,569 ops/sec ±1.68% (89 runs sampled)
✓ lodash.filter() x 31,812 ops/sec ±1.98% (89 runs sampled)

Result: fast.js is 71.25% faster than Array::filter().

Native .reduce() vs fast.reduce() (3 items)
✓ Array::reduce() x 5,265,085 ops/sec ±2.05% (92 runs sampled)
✓ fast.reduce() x 12,292,495 ops/sec ±1.92% (86 runs sampled)
✓ fast.reduce() v0.0.2c x 5,682,528 ops/sec ±1.70% (93 runs sampled)
✓ fast.reduce() v0.0.2b x 12,414,836 ops/sec ±1.64% (86 runs sampled)
✓ fast.reduce() v0.0.2a x 10,429,075 ops/sec ±2.13% (85 runs sampled)
✓ fast.reduce() v0.0.1 x 10,912,688 ops/sec ±1.89% (90 runs sampled)
✓ fast.reduce() v0.0.0 x 10,167,977 ops/sec ±2.15% (83 runs sampled)
✓ underscore.reduce() x 3,874,734 ops/sec ±1.83% (92 runs sampled)
✓ lodash.reduce() x 5,870,466 ops/sec ±1.51% (90 runs sampled)

Result: fast.js is 133.47% faster than Array::reduce().

Native .reduce() vs fast.reduce() (10 items)
✓ Array::reduce() x 2,231,469 ops/sec ±1.76% (95 runs sampled)
✓ fast.reduce() x 4,927,744 ops/sec ±2.14% (89 runs sampled)
✓ fast.reduce() v0.0.2c x 2,760,418 ops/sec ±1.67% (94 runs sampled)
✓ fast.reduce() v0.0.2b x 5,170,649 ops/sec ±1.75% (93 runs sampled)
✓ fast.reduce() v0.0.2a x 4,739,119 ops/sec ±1.52% (88 runs sampled)
✓ fast.reduce() v0.0.1 x 4,787,119 ops/sec ±1.55% (92 runs sampled)
✓ fast.reduce() v0.0.0 x 3,992,886 ops/sec ±2.10% (91 runs sampled)
✓ underscore.reduce() x 1,836,719 ops/sec ±2.33% (85 runs sampled)
✓ lodash.reduce() x 3,085,935 ops/sec ±1.61% (84 runs sampled)

Result: fast.js is 120.83% faster than Array::reduce().

Native .reduce() vs fast.reduce() (1000 items)
✓ Array::reduce() x 28,548 ops/sec ±1.60% (93 runs sampled)
✓ fast.reduce() x 65,531 ops/sec ±1.55% (92 runs sampled)
✓ fast.reduce() v0.0.2c x 40,967 ops/sec ±1.63% (94 runs sampled)
✓ fast.reduce() v0.0.2b x 64,443 ops/sec ±1.94% (87 runs sampled)
✓ fast.reduce() v0.0.2a x 64,029 ops/sec ±1.75% (88 runs sampled)
✓ fast.reduce() v0.0.1 x 64,980 ops/sec ±1.40% (90 runs sampled)
✓ fast.reduce() v0.0.0 x 50,497 ops/sec ±1.49% (95 runs sampled)
✓ underscore.reduce() x 29,694 ops/sec ±2.08% (92 runs sampled)
✓ lodash.reduce() x 51,844 ops/sec ±1.39% (91 runs sampled)

Result: fast.js is 129.55% faster than Array::reduce().

Native .reduceRight() vs fast.reduceRight() (3 items)
✓ Array::reduceRight() x 5,308,558 ops/sec ±1.93% (92 runs sampled)
✓ fast.reduceRight() x 13,242,382 ops/sec ±1.66% (87 runs sampled)
✓ underscore.reduceRight() x 4,004,525 ops/sec ±1.86% (87 runs sampled)
✓ lodash.reduceRight() x 4,156,965 ops/sec ±1.69% (89 runs sampled)

Result: fast.js is 149.45% faster than Array::reduceRight().

Native .reduceRight() vs fast.reduceRight() (10 items)
✓ Array::reduceRight() x 2,324,402 ops/sec ±1.29% (98 runs sampled)
✓ fast.reduceRight() x 5,247,608 ops/sec ±1.79% (92 runs sampled)
✓ underscore.reduceRight() x 1,989,666 ops/sec ±1.87% (90 runs sampled)
✓ lodash.reduceRight() x 2,456,215 ops/sec ±1.90% (89 runs sampled)

Result: fast.js is 125.76% faster than Array::reduceRight().

Native .reduceRight() vs fast.reduceRight() (1000 items)
✓ Array::reduceRight() x 28,344 ops/sec ±2.01% (86 runs sampled)
✓ fast.reduceRight() x 66,563 ops/sec ±1.69% (90 runs sampled)
✓ underscore.reduceRight() x 28,260 ops/sec ±1.78% (91 runs sampled)
✓ lodash.reduceRight() x 46,152 ops/sec ±1.75% (83 runs sampled)

Result: fast.js is 134.84% faster than Array::reduceRight().

Native .forEach() vs fast.forEach() (3 items)
✓ Array::forEach() x 1,943,052 ops/sec ±1.64% (93 runs sampled)
✓ fast.forEach() x 2,529,529 ops/sec ±2.02% (88 runs sampled)
✓ fast.forEach() v0.0.2a x 2,487,059 ops/sec ±2.00% (83 runs sampled)
✓ fast.forEach() v0.0.1 x 2,495,638 ops/sec ±2.17% (89 runs sampled)
✓ fast.forEach() v0.0.0 x 2,361,522 ops/sec ±1.75% (91 runs sampled)
✓ underscore.forEach() x 1,881,480 ops/sec ±1.72% (86 runs sampled)
✓ lodash.forEach() x 2,537,514 ops/sec ±2.05% (86 runs sampled)

Result: fast.js is 30.18% faster than Array::forEach().

Native .forEach() vs fast.forEach() (10 items)
✓ Array::forEach() x 724,480 ops/sec ±2.01% (81 runs sampled)
✓ fast.forEach() x 940,274 ops/sec ±2.22% (92 runs sampled)
✓ fast.forEach() v0.0.2a x 899,968 ops/sec ±2.38% (87 runs sampled)
✓ fast.forEach() v0.0.1 x 890,376 ops/sec ±2.02% (86 runs sampled)
✓ fast.forEach() v0.0.0 x 864,752 ops/sec ±2.05% (82 runs sampled)
✓ underscore.forEach() x 715,193 ops/sec ±1.93% (90 runs sampled)
✓ lodash.forEach() x 919,266 ops/sec ±2.16% (84 runs sampled)

Result: fast.js is 29.79% faster than Array::forEach().

Native .forEach() vs fast.forEach() (1000 items)
✓ Array::forEach() x 9,019 ops/sec ±0.97% (94 runs sampled)
✓ fast.forEach() x 11,736 ops/sec ±1.40% (93 runs sampled)
✓ fast.forEach() v0.0.2a x 11,277 ops/sec ±1.89% (91 runs sampled)
✓ fast.forEach() v0.0.1 x 11,038 ops/sec ±2.19% (90 runs sampled)
✓ fast.forEach() v0.0.0 x 10,689 ops/sec ±1.64% (93 runs sampled)
✓ underscore.forEach() x 9,179 ops/sec ±0.95% (97 runs sampled)
✓ lodash.forEach() x 11,877 ops/sec ±0.80% (96 runs sampled)

Result: fast.js is 30.12% faster than Array::forEach().

Native .some() vs fast.some() (3 items)
✓ Array::some() x 6,159,633 ops/sec ±0.72% (93 runs sampled)
✓ fast.some() x 17,439,338 ops/sec ±0.95% (97 runs sampled)
✓ underscore.some() x 5,321,608 ops/sec ±1.83% (93 runs sampled)
✓ lodash.some() x 9,950,629 ops/sec ±1.50% (91 runs sampled)

Result: fast.js is 183.12% faster than Array::some().

Native .some() vs fast.some() (10 items)
✓ Array::some() x 2,609,126 ops/sec ±2.08% (96 runs sampled)
✓ fast.some() x 8,213,940 ops/sec ±0.57% (97 runs sampled)
✓ underscore.some() x 2,515,201 ops/sec ±1.59% (92 runs sampled)
✓ lodash.some() x 5,985,594 ops/sec ±0.70% (97 runs sampled)

Result: fast.js is 214.82% faster than Array::some().

Native .some() vs fast.some() (1000 items)
✓ Array::some() x 37,842 ops/sec ±0.76% (95 runs sampled)
✓ fast.some() x 113,145 ops/sec ±1.25% (97 runs sampled)
✓ underscore.some() x 38,048 ops/sec ±0.77% (100 runs sampled)
✓ lodash.some() x 110,207 ops/sec ±2.25% (93 runs sampled)

Result: fast.js is 199.00% faster than Array::some().

Native .concat() vs fast.concat() (3 items)
✓ Array::concat() x 1,449,391 ops/sec ±1.44% (94 runs sampled)
✓ fast.concat() x 7,111,475 ops/sec ±0.74% (96 runs sampled)

Result: fast.js is 390.65% faster than Array::concat().

Native .concat() vs fast.concat() (10 items)
✓ Array::concat() x 1,234,073 ops/sec ±1.21% (94 runs sampled)
✓ fast.concat() x 5,076,888 ops/sec ±0.92% (96 runs sampled)

Result: fast.js is 311.39% faster than Array::concat().

Native .concat() vs fast.concat() (1000 items)
✓ Array::concat() x 793,363 ops/sec ±0.59% (92 runs sampled)
✓ fast.concat() x 184,319 ops/sec ±1.50% (95 runs sampled)

Result: fast.js is 76.77% slower than Array::concat().

Native .concat() vs fast.concat() (1000 items, using apply)
✓ Array::concat() x 40,878 ops/sec ±0.75% (94 runs sampled)
✓ fast.concat() x 78,605 ops/sec ±1.27% (94 runs sampled)

Result: fast.js is 92.29% faster than Array::concat().

Finished in 1774 seconds
```

(SpiderMonkey results to follow, it takes a while to run...)