# cache-require-paths > Caches resolved paths in module require to avoid Node hunting for right module. Speeds up app load. [![NPM][cache-require-paths-icon] ][cache-require-paths-url] [![Build status][cache-require-paths-ci-image] ][cache-require-paths-ci-url] [![semantic-release][semantic-image] ][semantic-url] [cache-require-paths-icon]: https://nodei.co/npm/cache-require-paths.png?downloads=true [cache-require-paths-url]: https://npmjs.org/package/cache-require-paths [cache-require-paths-ci-image]: https://travis-ci.org/bahmutov/cache-require-paths.png?branch=master [cache-require-paths-ci-url]: https://travis-ci.org/bahmutov/cache-require-paths [semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg [semantic-url]: https://github.com/semantic-release/semantic-release This is a partial solution to Node "hunting" for right file to load when you require a 3rd party dependency. See [Node’s `require` is dog slow](https://kev.inburke.com/kevin/node-require-is-dog-slow/) and [Faster Node app require](http://glebbahmutov.com/blog/faster-node-app-require/) for details. ## Use npm install --save cache-require-paths Load the module first in your application file ```js // index.js require('cache-require-paths'); ... ``` The first time the app loads, a cache of resolved file paths will be saved to `.cache-require-paths.json` in the current directory. Every application startup after that will reuse this filename cache to avoid "hunting" for the right filename. To save cached paths to a different file, set the environmental variable `CACHE_REQUIRE_PATHS_FILE`. ## Results Here are results for loading common packages without and with caching resolved require paths. You can run any of this experiments inside the `test` folder. `node index.js` loads using the standard resolve. `node index.js --cache` uses a cache of the resolves paths. Using node 0.10.37 require('X') | standard (ms) | with cache (ms) | speedup (%) ------------------------------------------------------------------ express@4.12.3 | 72 | 46 | 36 karma@0.12.31 | 230 | 170 | 26 grunt@0.4.5 | 120 | 95 | 20 sails@0.11.0 | 170 | 120 | 29 Using node 0.12.2 - all startup times became slower. require('X') | standard (ms) | with cache (ms) | speedup (%) ------------------------------------------------------------------ express@4.12.3 | 90 | 55 | 38 karma@0.12.31 | 250 | 200 | 20 grunt@0.4.5 | 150 | 120 | 20 sails@0.11.0 | 200 | 145 | 27 ## TODO - [ ] Cache only the absolute paths (relative paths resolve quickly) - [ ] Invalidate cache if dependencies in the package.json change ## Discussion You can see Node on Mac OS X searchig for a file to load when loading an absolute path like `require(express)` by using the following command to make a log of all system level calls from Node (start this from another terminal before running node program) sudo dtruss -d -n 'node' > /tmp/require.log 2>&1 Then run the test program, for example in the `test` folder run $ node index.js Kill the `dtruss` process and open the generated `/tmp/require.log`. It shows every system call with the following 4 columns: process id (should be single node process), relative time (microseconds), system call with arguments, and after the equality sign the numerical result of the call. When loading `express` dependency from the test program using `require('express');` we see the following search (I abbreviated paths for clarity): # microseconds call 664730 stat64(".../test/node_modules/express\0", 0x7FFF5FBFECF8, 0x204) = 0 0 664784 stat64(".../test/node_modules/express.js\0", 0x7FFF5FBFED28, 0x204) = -1 Err#2 664834 stat64(".../test/node_modules/express.json\0", 0x7FFF5FBFED28, 0x204) = -1 Err#2 664859 stat64(".../test/node_modules/express.node\0", 0x7FFF5FBFED28, 0x204) = -1 Err#2 664969 open(".../test/node_modules/express/package.json\0", 0x0, 0x1B6) = 11 0 664976 fstat64(0xB, 0x7FFF5FBFEC38, 0x1B6) = 0 0 665022 read(0xB, "{\n \"name\": \"express\", ...}", 0x103D) = 4157 0 665030 close(0xB) = 0 0 By default, Node checks if the local `node_modules/express` folder exists first (first `stat64` call), Then it tries to check the status of the `node_modules/express.js` file and fails. Then `node_modules/express.json` file. Then `node_modules/express.node` file. Finally it opens the `node_modules/express/package.json` file and reads the contents. Note that this is not the end of the story. Node loader only loads `express/package.json` to fetch `main` filename or use the default `index.js`! Each wasted file system call takes only 100 microseconds, but the tiny delays add up to hundreds of milliseconds and finally seconds for larger frameworks. Profile the same program with `--cache` option added to the command line arguments $ node index.js --cache This option loads the `cache-require-paths` module as the first require of the application ```js var useCache = process.argv.some(function (str) { return str === '--cache'; }); if (useCache) { console.log('using filename cache'); require('cache-require-paths'); } ``` The trace now shows *no calls to find `express` package*, just straight load of the `express/index.js` file. 643466 stat64(".../node_modules/express/index.js\0", 0x7FFF5FBFED28, 0x3) = 0 0 643501 lstat64(".../node_modules\0", 0x7FFF5FBFED08, 0x3) = 0 0 643513 lstat64(".../node_modules/express\0", 0x7FFF5FBFED08, 0x3) = 0 0 643523 lstat64(".../node_modules/express/index.js\0", 0x7FFF5FBFED08, 0x3) = 0 0 643598 open(".../node_modules/express/index.js\0", 0x0, 0x1B6) = 12 0 643600 fstat64(0xC, 0x7FFF5FBFED58, 0x1B6) = 0 0 Mission achieved. Note that the speedup only happens after the first application run finishes successfully. The resolution cache needs to be saved to a local file, and this happens only on process exit. ## Small print Author: Gleb Bahmutov © 2015 * [@bahmutov](https://twitter.com/bahmutov) * [glebbahmutov.com](http://glebbahmutov.com) * [blog](http://glebbahmutov.com/blog) License: MIT - do anything with the code, but don't blame me if it does not work. Spread the word: tweet, star on github, etc. Support: if you find any problems with this module, email / tweet / [open issue](https://github.com/bahmutov/cache-require-paths/issues) on Github