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
Windows build performance #10399
Windows build performance #10399
Conversation
In windows, source is in posix format and missing a trailing slash, causing the symlink to always be recreated.
It is never used in the bundles created by "meteor run", and adds 0.5 - 1.5 seconds per build for smaller apps.
Since the server is always stopped when building the server, it should be safe to overwrite it's files.
This is most noticible in copyNodeModulesDirectory, which is called many times during each server build.
The path was in the wrong format, so .meteor-portable.json was never saved.
Creating the watcher can take up to 12+ seconds in small - medium apps, and uses sync fs calls. The server would start right away, but the tool process wouldn't know about it until the watcher finished setting up. Also, the proxy doesn't forward requests until "=> Server restarted" is shown. A new async option is added to Watcher which prevents it from blocking the event loop too long. Also, the watcher and legacy bundle are only created after the server has started, or 3 seconds has passed.
enableCache was called before readdir and realpath was added to "files".
Most directories are in the WatchSet at least twice, and the directory is read and each item is stat each time. In addition, when the watcher is not created by isUpToDate, each item in watchSet.directories and watchSet.files is checked twice. With these changes, isUpToDate finishes in less than 1/2 the time on Windows, and creating a watcher takes around 1/4 the time.
After the last 4 comments, the build now is: InitialresolveConstraints: same Rebuild client and serverprepareProjectForBuild: 1,762 797 958 Usable after 5,579 Client only rebuild before last 4 commitsonChange: 2,562 3,389 3,136 Usable after 8,440 Client only rebuild after last 4 commitsonChange: 1,162 1,108 1,048 The client only rebuilds are timed before the server is rebuilt for the first time. After the initial build, the watch sets seems to include every folder and some files in |
In my limited local testing, this PR makes rebuilds FASTER under Windows than under a Linux VM on the same machine! |
fast-windows-meteor-rebuild.zip A quick stop watch test shows 23 seconds rebuild, vs 24 seconds in a VM (save to browser response). Much improved over the 80-100 (or more) seconds it used to take. |
Since this is not targeted at Linux, I didn't expect huge gains, but I can confirm that rebuild times are within variance and didn't change on Linux. I'd like to do some more accurate measurements but GC is getting in my way at the moment |
I'm having build times of more than 2 minutes. This patch would be more very, very welcome! |
5e26ebb
to
adaf653
Compare
I haven't had time to give this PR a thorough review yet, but we will definitely be including this PR in Meteor 1.8.1, in case there was any doubt. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much for working on this @zodern! This looks awesome and your benchmarking results are amazing! Tool changes like these can definitely be tricky, so we'll plan on getting these changes into a published beta release, to let people try them out. Thanks again for your work here!
Something is causing the spinner to remain after it is finished spinning:
|
It seems that removing that 3 second race might have added back the lengthy end of build delay. I'll do more testing with and without and see if it reveals anything. |
I just have to say, this is so fast, and makes Meteor on Windows such a pleasure to use. I can't wait until this is merged. I haven't noticed any delay after rebuild - either there isn't one, or it's just so fast I can't tell. Awesome work! |
Is this branch present in the current beta release? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go ahead and get this into a beta build so folks can use it. None of my feedback is worth delaying the beta release.
To use the newest release, do i install normally using choco , then replace the files in the .meteor folder with the ones in the 1.8.1 repo? |
@tabasco-addict Install via choco (which will give you Meteor 1.8.0.2) and then run meteor update --release 1.8.1-beta.16 in any application directory. You can also create a new app with meteor create --release 1.8.1-beta.16 new-181b16-app |
Okay, this one is officially awesome! Thanks @zodern and @benjamn! My build time (hot update) went down from 42 seconds to 9 seconds. Waiting for the browser refresh, takes another 5 seconds. Usually, Meteor starts to be slower after a couple of hours development with a number of rebuilds. So I still need to monitor that one. But I have good hope. I've installed Ubuntu 2 days ago. Turns out, that that was either a year too late, or a day to soon. |
Before:
The times are from the todos app. Rebuilds are for editing a file that is only used in the client, but not in a
client
folder, causing both the server and clients to be rebuilt.Initial build (second and later runs):
resolveContraints: 2,149 2,261
prepareProjectForBuild: 10,299 11,230
build app: 20,656 18,792
App process started after: 36,902 35,839
Creating watchers finished: 12,383 13,462ms after app started
AppProcess onListen: 23,900 25,644ms after app started
Usuable after: 60,802 61,483
Rebuild
prepareProjectForBuild: 6,713 6,674 7,158
rebuildApp: 4,555 4,269 4,008
App process started after: 11,690 11,499 11,621
Creating watchers finished: 4,536 4,057 4,001ms after app started
AppProcess onListen: 8,746 8,090 8,015ms after app started
Delayed build: 9,469 8,484 8,406ms after app started
Usuable after: 20,436 19,589 19,636
Delayed build at: 21,159 19,983 20,027
After:
Initial build (second and later runs):
resolveContraints: 1,392 1,879 2,053
prepareProjectForBuild: 6,601 7,267 6,708
build app: 16,056 14,270 12,810
App process started after: 28,662 26,679 24,557
AppProcess onListen: 2,007 2,214 1,593 after app started
Watchers are created after onListen and are no longer blocking
Usuable after: 30,669 28,893 26,150
Rebuild
prepareProjectForBuild: 6,187 6,013 6,359
rebuildApp: 2,587 2,297 1,842
App process started after: 9,256 8,757 8,811
AppProcess onListen: 1,936 1,894 1,697 after app started
Delayed build: 6,255 6,522 6,551 after app started
Usuable after: 11,192 10,651 10,508
Usuable + delayed build: 15,511 15,279 15,362
Notable Changes
The large app times are from the rebuild profile at #5091 (comment).
Delete garbage directories async
Saves 500 - 1,100ms per rebuild (large app 9s)
Do not use atomicallyRewriteFile when not building in place
Saves ~650ms (large app ~29,000ms including legacy bundle) per build.
This should be safe since the build is only used once all files have been successfully written. Renaming the two files takes almost twice as long as writing it.
isPortable
Saves ~900ms. Since npm-rebuilds.json is never used from the bundle created by "meteor run", creating it's contents is skipped.
The
.meteor-portable
file to cache the results was never created on Windows due to the file path being in the wrong format, which slowed down the initial build andmeteor build
when using local packages.inPlace server builds on windows and caching _copyDirectory
Saves 1 - 1.5s per rebuild. Most of the warnings against doing this on windows give the reason of interfering with the running app. Since the server is always stopped during the build, it should be safe to update it in place.
If it is safe to update the server in place, it might also be safe to do the same with the legacy bundle since the server doesn't serve it while it is being written.
Create file watcher and start legacy bundle after server started
Both of those were blocking the event loop, causing a delay between the server starting, and the tool process logging '=> server started' and letting the proxy know to forward requests.
Watcher now has an option to do the initial check async. The delayed legacy bundle blocking has not been fixed.