Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.3k
Description
repost of nodejs/node-v0.x-archive#7902 to ensure it is not lost, as per @jasnell suggestion.
credit goes to @joliss I am merely transplanting the issue.
The fs.realpath function is 70x slower than native C realpath. On my system, fs.realpath takes 32 µs, while C realpath takes 0.45 µs.
This is a real problem in the Broccoli build tool, where we need to resolve symlinks in hot code paths. Resolving 1000 symlinked files - not an unusual case - would take 45 ms, slowing down the build considerably. [1]
As for a solution: I haven't looked at the fs.js source in detail, but it seems we might be able to call the realpath function in the C standard library, where available, instead of using our own implementation.
Benchmark code for Node:
varfs=require('fs')varstart=Date.now()varn=10000for(vari=0;i<n;i++){if(fs.realpathSync('.')==='dummy')thrownewError('never happens')}console.log(((Date.now()-start)*1000/n)+' us')// => 32 us on Node 0.11.13Benchmark code for C:
#include <limits.h> /* PATH_MAX */ #include <stdio.h> #include <stdlib.h> // Adapted from http://stackoverflow.com/a/1563237/525872 int main(void) {charbuf[PATH_MAX+1];/* not sure about the "+ 1" */inti;for(i=0;i<1000000;i++){char*res=realpath(".",buf);if(res){// printf("This source is at %s.\n", buf);} else {perror("realpath");exit(EXIT_FAILURE);}}return0;}Run with gcc -std=gnu99 realpath-benchmark.c -o realpath-benchmark && time ./realpath-benchmark. This yields 0.45 µs per iteration on my Linux system.
[1] We cannot work around this by using naïve string concatenation, because path_resolution(7) requires that we resolve symlinks in all path components. Here is a gist to show why this matters.