Uh oh!
There was an error while loading. Please reload this page.
Reduce syscalls on require() - #1920
Conversation
There was a problem hiding this comment.
There should at least be a space here between if and (.
The comment should be modified slightly to read: // Don't search further if path doesn't exist
mscdex
commented
Jun 8, 2015
The subsystem the commit is targeting should be |
951fc5b to
a2d873cCompareFishrock123
commented
Jun 9, 2015
Is this before or after #1801, or does that not make a difference? EDIT: ah that may not matter. |
pierreinglebert
commented
Jun 9, 2015
It's after but it makes no difference. |
sam-github
commented
Jun 9, 2015
If this can improve node startup time, I'm all for it. Some of my CLIs take 400-500ms to start up, all in require, mostly statting non-existent directories. That doesn't sound like much, but under unit test, when the CLIs are spawned dozen's of times per test, it adds up very quickly. |
trevnorris
commented
Jun 9, 2015
Change looks sound. @isaacs Know of a reason why this would be a problem? |
Fishrock123
commented
Jun 9, 2015
Ah, didn't realize this was a PR. SGTM.. CI: https://jenkins-iojs.nodesource.com/view/iojs/job/iojs+any-pr+multi/787/ |
Fishrock123
commented
Jun 9, 2015
Looking at the CI I do not think this patch works on FreeBSD, SmartOS, or Windows. |
pierreinglebert
commented
Jun 9, 2015
The errors are suite strange, both freebsd throw 'Error: listen EADDRINUSE 0.0.0.0:12346' |
trevnorris
commented
Jun 9, 2015
It does appear that everything that failed is network related. @rvagg You seen this happen before with Jenkins? |
jbergstroem
commented
Jun 9, 2015
I found lingering processes on some machines (freebsd, smartos). We just discussed this in the build group and will be looking at making these tests more robust and/or reaping processes on test exit. |
trevnorris
commented
Jun 9, 2015
@jbergstroem should we be good to run CI again? |
jbergstroem
commented
Jun 9, 2015
@trevnorris feel free. The windows bots at least seems to give proper feedback (800+ failing tests because they can't be run): https://jenkins-iojs.nodesource.com/view/iojs/job/iojs+any-pr+multi/787/nodes=win2008r2/tapTestReport/test.tap-5/ |
trevnorris
commented
Jun 9, 2015
@jbergstroem thanks. looks like jenkins hasn't been happy the last few builds. :( Having another go at it: https://jenkins-iojs.nodesource.com/job/iojs+any-pr+multi/789/ |
jbergstroem
commented
Jun 9, 2015
@trevnorris yeah, its really unfortunate. |
isaacs
commented
Jun 9, 2015
The change seems fine to me. However, I'd love to see a test for this. Is it possible to monkey-patch fs.statSync and track which things get statted to create a failing test? |
isaacs
commented
Jun 9, 2015
Oh, I guess with the change in #1801, testing this might be a bit tricky. @bnoordhuis do you have any insight? If it's just not possible, and it doesn't make any existing tests fail (and doesn't, eg, break npm's or request's or express's tests) then LGTM. |
trevnorris
commented
Jun 9, 2015
this does make windows blow up hard: I'm guessing this error is specifically related to this PR. |
chrisdickinson
commented
Jun 9, 2015
I wonder how many packages test for presence of a module, generate it on "does not exist", then re-require it? I wouldn't advocate such an approach, of course, but it's within the realm of possibility. Do we want to support that use case? |
trevnorris
commented
Jun 9, 2015
@chrisdickinson how would that even be implemented? |
chrisdickinson
commented
Jun 9, 2015
try{varourCompiledModule=require('./generated.js')}catch(err){fs.writeFileSync(__dirname+'/generated.js','module.exports = 3','utf8');}Also, consider the REPL use case: |
trevnorris
commented
Jun 9, 2015
@chrisdickinson do you mention that as a possible new feature? Or is that something that works today? |
During require search, check the path exists before searching further in it.
a2d873c to
a10ce67Comparepierreinglebert
commented
Jun 11, 2015
On Unix systems, when the request path was absolute, it removed all the search paths but not on Windows, the |
chrisdickinson
commented
Jun 11, 2015
@trevnorris as a thing that works today that would not work if we cached "ENOENT" results to avoid syscalls. |
pierreinglebert
commented
Jun 11, 2015
This PR doesn't cache 'ENOENT' between require() calls, it just avoid calling stat/open on files if the directory doesn't exist. That wont break your usecase. |
pierreinglebert
commented
Jun 12, 2015
@trevnorris Could you run this PR on jenkins again ? |
trevnorris
commented
Jun 12, 2015
@bnoordhuis thanks. CI looks happy. LGTM. |
chrisdickinson
commented
Jun 12, 2015
One second – going to check this locally first just to make sure / prove that I'm just being paranoid. |
chrisdickinson
commented
Jun 12, 2015
Myth: CONFIRMED. I was just being paranoid. LGTM :) |
require() now checks that the path exists before searching further in it. PR-URL: #1920 Reviewed-By: Isaac Z. Schlueter <i@izs.me> Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Fishrock123
commented
Jun 18, 2015
Thanks, landed in a71ee93! |
PR-URL: #1996 Notable changes * module: The number of syscalls made during a require() have been significantly reduced again (see #1801 from v2.2.0 for previous work), which should lead to a performance improvement (Pierre Inglebert) #1920. * npm: - Upgrade to v2.11.2 (Rebecca Turner) #1956. - Upgrade to v2.11.3 (Forrest L Norvell) #2018. * zlib: A bug was discovered where the process would abort if the final part of a zlib decompression results in a buffer that would exceed the maximum length of 0x3fffffff bytes (~1GiB). This was likely to only occur during buffered decompression (rather than streaming). This is now fixed and will instead result in a thrown RangeError (Michaël Zasso) #1811.
PR-URL: #1996 Notable changes * module: The number of syscalls made during a require() have been significantly reduced again (see #1801 from v2.2.0 for previous work), which should lead to a performance improvement (Pierre Inglebert) #1920. * npm: - Upgrade to v2.11.2 (Rebecca Turner) #1956. - Upgrade to v2.11.3 (Forrest L Norvell) #2018. * zlib: A bug was discovered where the process would abort if the final part of a zlib decompression results in a buffer that would exceed the maximum length of 0x3fffffff bytes (~1GiB). This was likely to only occur during buffered decompression (rather than streaming). This is now fixed and will instead result in a thrown RangeError (Michaël Zasso) #1811.
In some conditions, require makes many useless syscalls trying to find files in non-existent directories.
For example, this is a
require('moment');in one subfolder of my project, the lib/sub/node_modules doesn't even exist.This PR divides by 7 the number of syscalls when requiring a module from a directory without node_modules at the cost of adding 1 from a directory with.
From my tests with a whole process doing only
require('express'), I pass from 760stat64to 574 (-25%) and from 106open_nocancelto 58 (45%).