Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upbuild: mtime cache for patches to speed up build #25881
Conversation
|
@dsanders11 the failure is owing to a small issue fixed in And this looks really exciting! I'll give it a more thorough review come Monday |
5b00b5f
to
a91a856
a91a856
to
2da5656
|
@codebytere, thanks! I've rebased it on Looking forward to the more thorough review. |
|
@dsanders11 had some more time to read into this and pull it down to play with it today - conceptually this looks good to me (and resulted in significant local speedup I would also be potentially open to running with this by default and/or in testing CI but would like a second opinion from @nornagon! |
|
@codebytere, flipped the feature on, the CI builds look good, just a test failure on macos which seems unlikely to be related. |
|
Thanks for this; this is an idea I've had in the back of my head for a while and never got around to implementing. I think this approach is fairly sound. The main concerns I can think of are:
I think we're relatively ok with (1) because of the sha1 step. However, as an additional precaution we should probably delete the mtime-cache.json file after applying it. I suspect (2) is not possible, because gclient will always want to reset repos to the version listed in Requesting changes for the cache file cleanup. |
Agreed on this concern, and the more nefarious situation where a build works but it's not what you expected it to be. That's why I've initially made it opt-in by defaulting the flag to false, since I didn't want to be responsible for causing cryptic build issues.
This seems reasonable, and something I'd considered during implementation. It is a slight trade-off in the "difficult to debug" direction since it leaves no trace. I think I'll add a flag
I came to the same conclusion, after initially investigating how patches were applied since I wasn't familiar. |
|
RE (2) in theory you could |
|
@MarshallOfSound applying the patches is pretty quick, I don't think it's worth the complexity of creating and managing new refs.
|
|
Made a new commit. Doing some more local testing I was seeing weird results from So, the latest commit changed:
@ckerr, @nornagon, please review the latest commit. Apologies for the thrash, but the no non-zero exit code change was important for robustness. I should be done touching it now that's done. |
|
I'm still |
I've been moving back and forth between branches and have no problems to report so far! |
f7945ad
into
electron:master
|
No Release Notes |
Description of Change
Motivation
Due to how patches are applied in the build system, a
gclient syncwill cause a subsequent build to rebuild a lot of code unnecessarily, because Ninja thinks it has changed as a result of the patching, even if it is identical to what it was before the sync.This causes me a lot of unnecessary grief around
gclient sync, since on the machine I'm using (which is a slow 4-core) the rebuilding will take 1-2 hours. That kind of downtime makes me weary of syncing due to how much it disrupts the workflow.Since most of the time the patches haven't changed due to the sync, and the patched files still have the same content post-sync, I looked for a way to prevent the unnecessary rebuilding and cut down the rebuild time after a sync.
Implementation
The implementation is fairly simple. Since Ninja is an mtime-based build system (and seems to have no desire to include file hashing), mtime is all that matters for preventing unnecessary rebuilding.
The goal is to carry forward the mtime for patched files across
gclient syncas long as they didn't change as a result of the sync. This lets them appear unchanged (to Ninja) by the sync like other files, even though they were reverted and patched again.Thankfully GN has pre-DEPS hooks, which made the implementation pretty easy. I've added a pre-DEPS hook which will run before
gclient syncstarts changing files, and this hook walks all patched files and creates a cache of their contents hash and their current mtime and atime. It dumps this into a file to be accessed by the hook which runs after the sync.After sync completes and the patches are applied, there's a hook which reads the cache file and checks the files listed. As long as their hash has not changed, this hook will apply the mtime and atime from before the sync began. The only shortcoming with the current implementation is it doesn't change the ctime (couldn't see a way to do it in Python), so the file metadata isn't quite identical to what it was before the sync, but that doesn't affect the build. I believe Ninja will only look at the mtime - I only included atime because the Python command to change mtime also took atime, and it was easy enough to throw in.
Due to potential for unintended side effects (I think it's pretty safe, but would like to solicit feedback) I made the feature opt-in under the
use_mtime_cacheflag in DEPS.Results
Builds after a
gclient syncare significantly faster. Before after any sync I would be looking at a rebuild with 16,000 tasks or so, and it would take over an hour. Now when doing agclient syncwhen there's nothing new to pull down I see Ninja shows 127 tasks and only takes about 5 minutes to build. This makes it "safe" for me to dogclient syncto my heart's content without worrying about having hours of rebuilding as a result, so it's a major improvement to workflow.cc @codebytere @MarshallOfSound
Checklist
Release Notes
Notes: none