diff options
author | Robin Appelman <robin@icewind.nl> | 2024-02-16 12:34:07 +0100 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2024-03-04 13:57:31 +0100 |
commit | a9ee278ec6059d164ed2f45b0eb304e940ffd588 (patch) | |
tree | 5182ea3e384f7c9f91976570e5eb48fe18fcbef4 /lib | |
parent | e7a7b4a40184dc3da2c83e858c820625f660e48e (diff) | |
download | nextcloud-server-a9ee278ec6059d164ed2f45b0eb304e940ffd588.tar.gz nextcloud-server-a9ee278ec6059d164ed2f45b0eb304e940ffd588.zip |
perf: cache path by id to speedup getting nodes by id
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Files/Node/Root.php | 30 | ||||
-rw-r--r-- | lib/private/Server.php | 5 |
2 files changed, 32 insertions, 3 deletions
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index bc76640966e..71bc7a6da6b 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -49,6 +49,8 @@ use OCP\Files\Mount\IMountPoint; use OCP\Files\Node as INode; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -81,6 +83,7 @@ class Root extends Folder implements IRootFolder { private LoggerInterface $logger; private IUserManager $userManager; private IEventDispatcher $eventDispatcher; + private ICache $pathByIdCache; /** * @param Manager $manager @@ -94,7 +97,8 @@ class Root extends Folder implements IRootFolder { IUserMountCache $userMountCache, LoggerInterface $logger, IUserManager $userManager, - IEventDispatcher $eventDispatcher + IEventDispatcher $eventDispatcher, + ICacheFactory $cacheFactory, ) { parent::__construct($this, $view, ''); $this->mountManager = $manager; @@ -107,6 +111,7 @@ class Root extends Folder implements IRootFolder { $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () { $this->userFolderCache = new CappedMemoryCache(); }); + $this->pathByIdCache = $cacheFactory->createLocal('path-by-id'); } /** @@ -406,7 +411,28 @@ class Root extends Folder implements IRootFolder { } public function getFirstNodeByIdInPath(int $id, string $path): ?INode { - return current($this->getByIdInPath($id, $path)); + // scope the cache by user, so we don't return nodes for different users + if ($this->user) { + $cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id); + if ($cachedPath && str_starts_with($path, $cachedPath)) { + // getting the node by path is significantly cheaper than finding it by id + $node = $this->get($cachedPath); + // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path + // if the cached path is invalid or a different file now we fall back to the uncached logic + if ($node && $node->getId() === $id) { + return $node; + } + } + } + $node = current($this->getByIdInPath($id, $path)); + if (!$node) { + return null; + } + + if ($this->user) { + $this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath()); + } + return $node; } /** diff --git a/lib/private/Server.php b/lib/private/Server.php index 1aedd7d06ac..c956da4fdd8 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -448,14 +448,17 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('RootFolder', function (ContainerInterface $c) { $manager = \OC\Files\Filesystem::getMountManager(); $view = new View(); + /** @var IUserSession $userSession */ + $userSession = $c->get(IUserSession::class); $root = new Root( $manager, $view, - null, + $userSession->getUser(), $c->get(IUserMountCache::class), $this->get(LoggerInterface::class), $this->get(IUserManager::class), $this->get(IEventDispatcher::class), + $this->get(ICacheFactory::class), ); $previewConnector = new \OC\Preview\WatcherConnector( |