mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
inodes: unload inodes before checkout on Windows
Summary: On Windows, we never unload any inodes until EdenFS is restarted, thus, checkout times go up over time as more and more inodes are being loaded. While on Windows we don't keep track of what is referenced by the kernel, the checkout code will use the "precise inodes" code path when deciding what to update. This means that every inode that is in the overlay will get updated properly, and since the overlay is a superset of what is hydrated, we are guaranteed to always invalidate what we need to. Due to the above, this shouldn't result in any changes as we never gc the overlay, but that will come later, at which point checkout times will stop being more and more expensive as time goes. Reviewed By: chadaustin Differential Revision: D24634253 fbshipit-source-id: c7b838edc20589bbf92ff4e2b3abd079b9a4443d
This commit is contained in:
parent
e3c3133fd3
commit
1ed7eeef95
@ -895,29 +895,30 @@ folly::Future<CheckoutResult> EdenMount::checkout(
|
||||
ctx->start(this->acquireRenameLock());
|
||||
|
||||
checkoutTimes->didAcquireRenameLock = stopWatch.elapsed();
|
||||
#ifndef _WIN32
|
||||
|
||||
/**
|
||||
* If a significant number of tree inodes are loaded or referenced
|
||||
* by FUSE, then checkout is slow, because Eden must precisely
|
||||
* manage changes to each one, as if the checkout was actually
|
||||
* creating and removing files in each directory. If a tree is
|
||||
* unloaded and unmodified, Eden can pretend the checkout
|
||||
* operation blew away the entire subtree and assigned new inode
|
||||
* numbers to everything under it, which is much cheaper.
|
||||
*
|
||||
* To make checkout faster, enumerate all loaded, unreferenced
|
||||
* inodes and unload them, allowing checkout to use the fast path.
|
||||
*
|
||||
* Note that this will not unload any inodes currently referenced
|
||||
* by FUSE, including the kernel's cache, so rapidly switching
|
||||
* between commits while working should not be materially
|
||||
* affected.
|
||||
*/
|
||||
// If a significant number of tree inodes are loaded or referenced
|
||||
// by FUSE, then checkout is slow, because Eden must precisely
|
||||
// manage changes to each one, as if the checkout was actually
|
||||
// creating and removing files in each directory. If a tree is
|
||||
// unloaded and unmodified, Eden can pretend the checkout
|
||||
// operation blew away the entire subtree and assigned new inode
|
||||
// numbers to everything under it, which is much cheaper.
|
||||
//
|
||||
// To make checkout faster, enumerate all loaded, unreferenced
|
||||
// inodes and unload them, allowing checkout to use the fast path.
|
||||
//
|
||||
// Note that this will not unload any inodes currently referenced
|
||||
// by FUSE, including the kernel's cache, so rapidly switching
|
||||
// between commits while working should not be materially
|
||||
// affected.
|
||||
//
|
||||
// On Windows, most of the above is also true, but instead of files
|
||||
// being referenced by the kernel, the files are actually on disk. All
|
||||
// the files on disk must also be present in the overlay, and thus the
|
||||
// checkout code will take care of doing the right invalidation for
|
||||
// these.
|
||||
this->getRootInode()->unloadChildrenUnreferencedByFuse();
|
||||
|
||||
#endif // !1
|
||||
|
||||
auto rootInode = getRootInode();
|
||||
return serverState_->getFaultInjector()
|
||||
.checkAsync("inodeCheckout", getPath().stringPiece())
|
||||
|
@ -3343,7 +3343,6 @@ size_t TreeInode::unloadChildrenNow() {
|
||||
[](InodeBase*) { return true; });
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
size_t TreeInode::unloadChildrenUnreferencedByFuse() {
|
||||
auto treeChildren = getTreeChildren(this);
|
||||
return unloadChildrenIf(
|
||||
@ -3354,6 +3353,7 @@ size_t TreeInode::unloadChildrenUnreferencedByFuse() {
|
||||
[](InodeBase* child) { return child->getFuseRefcount() == 0; });
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
size_t TreeInode::unloadChildrenLastAccessedBefore(const timespec& cutoff) {
|
||||
// Unloading children by criteria is a bit of an intricate operation. The
|
||||
// InodeMap and tree's contents lock must be held simultaneously when
|
||||
|
@ -333,7 +333,6 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
*/
|
||||
size_t unloadChildrenNow();
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* Unload all children, recursively, neither referenced internally by Eden nor
|
||||
* by FUSE.
|
||||
@ -342,6 +341,7 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
*/
|
||||
size_t unloadChildrenUnreferencedByFuse();
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* Unload all unreferenced inodes under this tree whose last access time is
|
||||
* older than the specified cutoff.
|
||||
|
Loading…
Reference in New Issue
Block a user