-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fs.realpath 70x slower than native #2680
Comments
@stefanpenner, about your hot path: does it modify those symlinks (or parent directories) in the same hot path? If not, you could pass a For example, if you resolve a lot of symlinks in the same dir in a loop, it could help to use a single cache for all those |
Ah. @joliss ↑↑ |
@ChALkeR i was about to implement something (what i believe to be) very similar.
-- source: the docs |
@stefanpenner Also, each |
@Fishrock123 Btw I think the above fact isn't properly documented. |
I would agree, but largely due to this pattern not being very common in the stdlib, so i wasn't looking for it. I'll give this pattern a try in the next day or so and report back. It may prove to be a nice win. That being said, we shouldn't assume this is the solution and a fast |
Repost of @trevnorris at nodejs/node-v0.x-archive#7902 (comment)
|
Fwiw I'm +1 on using |
Why can't this be proposed to uv and we use it? |
Depends if it is available cross-platform or not. Looks like this would be on windows though? https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx |
IMHO Libuv would be the ideal place for this. |
Another options would be _fullpath, though we tend to prefer to use NT APIs. A quick search for how MinGW handles this tells that sadly none of these functions check for junction point loops, whereas realpath(3) does. I'd be fine having it in libuv, if someone wants to do the work :-) |
@saghul I would like to try my hand at implementing it :-) |
Go for it! |
Is the consensus then to wait for |
Since this is such low hanging fruit in terms of performance, I'd prefer we make the change to use |
|
@jhamhader awesome :) |
@jhamhader See the note for
Whereas Also:
Last, naming: it should be called @thefourtheye are you also working on this? Let's not duplicate efforts! :-) |
@saghul Currently:
I will try to finish that over the weekend. |
@saghul I completed the Linux part but couldn't test in other platforms. So lets go with @jhamhader's work itself. |
Resolving realpath using the above test:
Using cache with the native realpath degrades performance. However, one issue bothers me: Performance can be optimized by looking only for the full absolute path in the cache. However, then the 'test_lying_cache_liar' from test-fs-realpath.js fails - it 'fakes' partial path and expects us to resolve it according to cache. By not trying to resolve each path component, this behavior can not achieved. |
@jhamhader It is a documented behavior of
That behavior should not be broken, and I guess there is no way around the fact that «Native» implementation would be slower when |
Can you explain what this is getting at?
And the latter part is pointless since native would remove Stat calls. |
require('fs').realpathSync('/HOME/.config', {'/HOME': '/home/user/'})
'/home/user/.config' Is a perfectly fine usage example, isn't it? And that is currently documented. |
Fixes: nodejs#4002 Fixes: nodejs#5384 Fixes: nodejs#6563 Refs: nodejs#2680 (comment) PR-URL: nodejs#6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: nodejs#4002 Fixes: nodejs#5384 Fixes: nodejs#6563 Refs: nodejs#2680 (comment) PR-URL: nodejs#6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
Fixes: #4002 Fixes: #5384 Fixes: #6563 Refs: #2680 (comment) PR-URL: #6796 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Johan Bergström <[email protected]> Reviewed-By: Myles Borins <[email protected]>
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:
Benchmark code for C:
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.
The text was updated successfully, but these errors were encountered: