strong-tie/inbound-calls
0
1# reusify2 3[![npm version][npm-badge]][npm-url]4[![Build Status][travis-badge]][travis-url]5[![Coverage Status][coveralls-badge]][coveralls-url]6 7Reuse your objects and functions for maximum speed. This technique will8make any function run ~10% faster. You call your functions a9lot, and it adds up quickly in hot code paths.10 11```12$ node benchmarks/createNoCodeFunction.js13Total time 5313314Total iterations 10000000015Iteration/s 1882069.523648203616 17$ node benchmarks/reuseNoCodeFunction.js18Total time 5061719Total iterations 10000000020Iteration/s 1975620.83884860821```22 23The above benchmark uses fibonacci to simulate a real high-cpu load.24The actual numbers might differ for your use case, but the difference25should not.26 27The benchmark was taken using Node v6.10.0.28 29This library was extracted from30[fastparallel](http://npm.im/fastparallel).31 32## Example33 34```js35var reusify = require('reusify')36var fib = require('reusify/benchmarks/fib')37var instance = reusify(MyObject)38 39// get an object from the cache,40// or creates a new one when cache is empty41var obj = instance.get()42 43// set the state44obj.num = 10045obj.func()46 47// reset the state.48// if the state contains any external object49// do not use delete operator (it is slow)50// prefer set them to null51obj.num = 052 53// store an object in the cache54instance.release(obj)55 56function MyObject () {57 // you need to define this property58 // so V8 can compile MyObject into an59 // hidden class60 this.next = null61 this.num = 062 63 var that = this64 65 // this function is never reallocated,66 // so it can be optimized by V867 this.func = function () {68 if (null) {69 // do nothing70 } else {71 // calculates fibonacci72 fib(that.num)73 }74 }75}76```77 78The above example was intended for synchronous code, let's see async:79```js80var reusify = require('reusify')81var instance = reusify(MyObject)82 83for (var i = 0; i < 100; i++) {84 getData(i, console.log)85}86 87function getData (value, cb) {88 var obj = instance.get()89 90 obj.value = value91 obj.cb = cb92 obj.run()93}94 95function MyObject () {96 this.next = null97 this.value = null98 99 var that = this100 101 this.run = function () {102 asyncOperation(that.value, that.handle)103 }104 105 this.handle = function (err, result) {106 that.cb(err, result)107 that.value = null108 that.cb = null109 instance.release(that)110 }111}112```113 114Also note how in the above examples, the code, that consumes an istance of `MyObject`,115reset the state to initial condition, just before storing it in the cache.116That's needed so that every subsequent request for an instance from the cache,117could get a clean instance.118 119## Why120 121It is faster because V8 doesn't have to collect all the functions you122create. On a short-lived benchmark, it is as fast as creating the123nested function, but on a longer time frame it creates less124pressure on the garbage collector.125 126## Other examples127If you want to see some complex example, checkout [middie](https://github.com/fastify/middie) and [steed](https://github.com/mcollina/steed).128 129## Acknowledgements130 131Thanks to [Trevor Norris](https://github.com/trevnorris) for132getting me down the rabbit hole of performance, and thanks to [Mathias133Buss](http://github.com/mafintosh) for suggesting me to share this134trick.135 136## License137 138MIT139 140[npm-badge]: https://badge.fury.io/js/reusify.svg141[npm-url]: https://badge.fury.io/js/reusify142[travis-badge]: https://api.travis-ci.org/mcollina/reusify.svg143[travis-url]: https://travis-ci.org/mcollina/reusify144[coveralls-badge]: https://coveralls.io/repos/mcollina/reusify/badge.svg?branch=master&service=github145[coveralls-url]: https://coveralls.io/github/mcollina/reusify?branch=master146 