Skip to content

Commit 6c34975

Browse files
committed
more filesystem setup performance instrumentation
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 7aa7868 commit 6c34975

5 files changed

Lines changed: 71 additions & 20 deletions

File tree

lib/private/Files/Config/MountProviderCollection.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
use OC\Hooks\Emitter;
2828
use OC\Hooks\EmitterTrait;
29+
use OCP\Diagnostics\IEventLogger;
2930
use OCP\Files\Config\IHomeMountProvider;
3031
use OCP\Files\Config\IMountProvider;
3132
use OCP\Files\Config\IMountProviderCollection;
@@ -65,13 +66,29 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
6566
/** @var callable[] */
6667
private $mountFilters = [];
6768

69+
private IEventLogger $eventLogger;
70+
6871
/**
6972
* @param \OCP\Files\Storage\IStorageFactory $loader
7073
* @param IUserMountCache $mountCache
7174
*/
72-
public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
75+
public function __construct(
76+
IStorageFactory $loader,
77+
IUserMountCache $mountCache,
78+
IEventLogger $eventLogger
79+
) {
7380
$this->loader = $loader;
7481
$this->mountCache = $mountCache;
82+
$this->eventLogger = $eventLogger;
83+
}
84+
85+
private function getMountsFromProvider(IMountProvider $provider, IUser $user, IStorageFactory $loader): array {
86+
$class = str_replace('\\', '_', get_class($provider));
87+
$uid = $user->getUID();
88+
$this->eventLogger->start('fs:setup:provider:' . $class, "Getting mounts from $class for $uid");
89+
$mounts = $provider->getMountsForUser($user, $loader) ?? [];
90+
$this->eventLogger->end('fs:setup:provider:' . $class);
91+
return $mounts;
7592
}
7693

7794
/**
@@ -82,7 +99,7 @@ public function __construct(IStorageFactory $loader, IUserMountCache $mountCache
8299
private function getUserMountsForProviders(IUser $user, array $providers): array {
83100
$loader = $this->loader;
84101
$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
85-
return $provider->getMountsForUser($user, $loader);
102+
return $this->getMountsFromProvider($provider, $user, $loader);
86103
}, $providers);
87104
$mounts = array_filter($mounts, function ($result) {
88105
return is_array($result);
@@ -121,7 +138,7 @@ public function addMountForUser(IUser $user, IMountManager $mountManager, callab
121138
return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
122139
});
123140
foreach ($firstProviders as $provider) {
124-
$mounts = $provider->getMountsForUser($user, $this->loader);
141+
$mounts = $this->getMountsFromProvider($provider, $user, $this->loader);
125142
if (is_array($mounts)) {
126143
$firstMounts = array_merge($firstMounts, $mounts);
127144
}
@@ -131,14 +148,16 @@ public function addMountForUser(IUser $user, IMountManager $mountManager, callab
131148

132149
$lateMounts = [];
133150
foreach ($lastProviders as $provider) {
134-
$mounts = $provider->getMountsForUser($user, $this->loader);
151+
$mounts = $this->getMountsFromProvider($provider, $user, $this->loader);
135152
if (is_array($mounts)) {
136153
$lateMounts = array_merge($lateMounts, $mounts);
137154
}
138155
}
139156

140157
$lateMounts = $this->filterMounts($user, $lateMounts);
158+
$this->eventLogger->start("fs:setup:add-mounts", "Add mounts to the filesystem");
141159
array_walk($lateMounts, [$mountManager, 'addMount']);
160+
$this->eventLogger->end("fs:setup:add-mounts");
142161

143162
return array_merge($lateMounts, $firstMounts);
144163
}

lib/private/Files/Config/UserMountCache.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use OCP\Cache\CappedMemoryCache;
3232
use OCA\Files_Sharing\SharedMount;
3333
use OCP\DB\QueryBuilder\IQueryBuilder;
34+
use OCP\Diagnostics\IEventLogger;
3435
use OCP\Files\Config\ICachedMountFileInfo;
3536
use OCP\Files\Config\ICachedMountInfo;
3637
use OCP\Files\Config\IUserMountCache;
@@ -56,19 +57,27 @@ class UserMountCache implements IUserMountCache {
5657
private LoggerInterface $logger;
5758
/** @var CappedMemoryCache<array> */
5859
private CappedMemoryCache $cacheInfoCache;
60+
private IEventLogger $eventLogger;
5961

6062
/**
6163
* UserMountCache constructor.
6264
*/
63-
public function __construct(IDBConnection $connection, IUserManager $userManager, LoggerInterface $logger) {
65+
public function __construct(
66+
IDBConnection $connection,
67+
IUserManager $userManager,
68+
LoggerInterface $logger,
69+
IEventLogger $eventLogger
70+
) {
6471
$this->connection = $connection;
6572
$this->userManager = $userManager;
6673
$this->logger = $logger;
74+
$this->eventLogger = $eventLogger;
6775
$this->cacheInfoCache = new CappedMemoryCache();
6876
$this->mountsForUsers = new CappedMemoryCache();
6977
}
7078

7179
public function registerMounts(IUser $user, array $mounts, array $mountProviderClasses = null) {
80+
$this->eventLogger->start('fs:setup:user:register', 'Registering mounts for user');
7281
// filter out non-proper storages coming from unit tests
7382
$mounts = array_filter($mounts, function (IMountPoint $mount) {
7483
return $mount instanceof SharedMount || ($mount->getStorage() && $mount->getStorage()->getCache());
@@ -134,6 +143,7 @@ public function registerMounts(IUser $user, array $mounts, array $mountProviderC
134143
foreach ($changedMounts as $mount) {
135144
$this->updateCachedMount($mount);
136145
}
146+
$this->eventLogger->end('fs:setup:user:register');
137147
}
138148

139149
/**

lib/private/Files/SetupManager.php

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ public function setupForUser(IUser $user): void {
212212
}
213213
$this->setupUsersComplete[] = $user->getUID();
214214

215+
$this->eventLogger->start('fs:setup:user:full', 'Setup full filesystem for user');
216+
215217
if (!isset($this->setupUserMountProviders[$user->getUID()])) {
216218
$this->setupUserMountProviders[$user->getUID()] = [];
217219
}
@@ -226,6 +228,7 @@ public function setupForUser(IUser $user): void {
226228
});
227229
});
228230
$this->afterUserFullySetup($user, $previouslySetupProviders);
231+
$this->eventLogger->end('fs:setup:user:full');
229232
}
230233

231234
/**
@@ -237,6 +240,8 @@ private function oneTimeUserSetup(IUser $user) {
237240
}
238241
$this->setupUsers[] = $user->getUID();
239242

243+
$this->eventLogger->start('fs:setup:user:onetime', 'Onetime filesystem for user');
244+
240245
$this->setupBuiltinWrappers();
241246

242247
$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
@@ -250,14 +255,18 @@ private function oneTimeUserSetup(IUser $user) {
250255
Filesystem::initInternal($userDir);
251256

252257
if ($this->lockdownManager->canAccessFilesystem()) {
258+
$this->eventLogger->start('fs:setup:user:home', 'Setup home filesystem for user');
253259
// home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
254260
$homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
255261
$this->mountManager->addMount($homeMount);
256262

257263
if ($homeMount->getStorageRootId() === -1) {
264+
$this->eventLogger->start('fs:setup:user:home:scan', 'Scan home filesystem for user');
258265
$homeMount->getStorage()->mkdir('');
259266
$homeMount->getStorage()->getScanner()->scan('');
267+
$this->eventLogger->end('fs:setup:user:home:scan');
260268
}
269+
$this->eventLogger->end('fs:setup:user:home');
261270
} else {
262271
$this->mountManager->addMount(new MountPoint(
263272
new NullStorage([]),
@@ -271,12 +280,15 @@ private function oneTimeUserSetup(IUser $user) {
271280
}
272281

273282
$this->listenForNewMountProviders();
283+
284+
$this->eventLogger->end('fs:setup:user:onetime');
274285
}
275286

276287
/**
277288
* Final housekeeping after a user has been fully setup
278289
*/
279290
private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
291+
$this->eventLogger->start('fs:setup:user:full:post', 'Housekeeping after user is setup');
280292
$userRoot = '/' . $user->getUID() . '/';
281293
$mounts = $this->mountManager->getAll();
282294
$mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
@@ -296,6 +308,7 @@ private function afterUserFullySetup(IUser $user, array $previouslySetupProvider
296308
$this->cache->set($user->getUID(), true, $cacheDuration);
297309
$this->fullSetupRequired[$user->getUID()] = false;
298310
}
311+
$this->eventLogger->end('fs:setup:user:full:post');
299312
}
300313

301314
/**
@@ -312,17 +325,17 @@ private function setupForUserWith(IUser $user, callable $mountCallback): void {
312325
$this->oneTimeUserSetup($user);
313326
}
314327

315-
$this->eventLogger->start('setup_fs', 'Setup filesystem');
316-
317328
if ($this->lockdownManager->canAccessFilesystem()) {
318329
$mountCallback();
319330
}
331+
$this->eventLogger->start('fs:setup:user:post-init-mountpoint', 'post_initMountPoints legacy hook');
320332
\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
333+
$this->eventLogger->end('fs:setup:user:post-init-mountpoint');
321334

322335
$userDir = '/' . $user->getUID() . '/files';
336+
$this->eventLogger->start('fs:setup:user:setup-hook', 'setup legacy hook');
323337
OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
324-
325-
$this->eventLogger->end('setup_fs');
338+
$this->eventLogger->end('fs:setup:user:setup-hook');
326339
}
327340

328341
/**
@@ -335,7 +348,7 @@ public function setupRoot(): void {
335348
}
336349
$this->rootSetup = true;
337350

338-
$this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
351+
$this->eventLogger->start('fs:setup:root', 'Setup root filesystem');
339352

340353
$this->setupBuiltinWrappers();
341354

@@ -344,7 +357,7 @@ public function setupRoot(): void {
344357
$this->mountManager->addMount($rootMountProvider);
345358
}
346359

347-
$this->eventLogger->end('setup_root_fs');
360+
$this->eventLogger->end('fs:setup:root');
348361
}
349362

350363
/**
@@ -413,6 +426,9 @@ public function setupForPath(string $path, bool $includeChildren = false): void
413426
$this->oneTimeUserSetup($user);
414427
}
415428

429+
$this->eventLogger->start('fs:setup:user:path', "Setup $path filesystem for user");
430+
$this->eventLogger->start('fs:setup:user:path:find', "Find mountpoint for $path");
431+
416432
$mounts = [];
417433
if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
418434
$currentProviders[] = $cachedMount->getMountProvider();
@@ -421,13 +437,16 @@ public function setupForPath(string $path, bool $includeChildren = false): void
421437
$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
422438
} else {
423439
$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
440+
$this->eventLogger->end('fs:setup:user:path:find');
424441
$this->setupForUser($user);
442+
$this->eventLogger->end('fs:setup:user:path');
425443
return;
426444
}
427445
}
428446

429447
if ($includeChildren) {
430448
$subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
449+
$this->eventLogger->end('fs:setup:user:path:find');
431450

432451
$needsFullSetup = array_reduce($subCachedMounts, function (bool $needsFullSetup, ICachedMountInfo $cachedMountInfo) {
433452
return $needsFullSetup || $cachedMountInfo->getMountProvider() === '';
@@ -436,6 +455,7 @@ public function setupForPath(string $path, bool $includeChildren = false): void
436455
if ($needsFullSetup) {
437456
$this->logger->debug("mount has no provider set, performing full setup");
438457
$this->setupForUser($user);
458+
$this->eventLogger->end('fs:setup:user:path');
439459
return;
440460
} else {
441461
foreach ($subCachedMounts as $cachedMount) {
@@ -446,6 +466,8 @@ public function setupForPath(string $path, bool $includeChildren = false): void
446466
}
447467
}
448468
}
469+
} else {
470+
$this->eventLogger->end('fs:setup:user:path:find');
449471
}
450472

451473
if (count($mounts)) {
@@ -456,6 +478,7 @@ public function setupForPath(string $path, bool $includeChildren = false): void
456478
} elseif (!$this->isSetupStarted($user)) {
457479
$this->oneTimeUserSetup($user);
458480
}
481+
$this->eventLogger->end('fs:setup:user:path');
459482
}
460483

461484
private function fullSetupRequired(IUser $user): bool {
@@ -488,6 +511,8 @@ public function setupForProvider(string $path, array $providers): void {
488511
return;
489512
}
490513

514+
$this->eventLogger->start('fs:setup:user:providers', "Setup filesystem for " . implode(', ', $providers));
515+
491516
// home providers are always used
492517
$providers = array_filter($providers, function (string $provider) {
493518
return !is_subclass_of($provider, IHomeMountProvider::class);
@@ -504,6 +529,7 @@ public function setupForProvider(string $path, array $providers): void {
504529
if (!$this->isSetupStarted($user)) {
505530
$this->oneTimeUserSetup($user);
506531
}
532+
$this->eventLogger->end('fs:setup:user:providers');
507533
return;
508534
} else {
509535
$this->setupUserMountProviders[$user->getUID()] = array_merge($setupProviders, $providers);
@@ -514,6 +540,7 @@ public function setupForProvider(string $path, array $providers): void {
514540
$this->setupForUserWith($user, function () use ($mounts) {
515541
array_walk($mounts, [$this->mountManager, 'addMount']);
516542
});
543+
$this->eventLogger->end('fs:setup:user:providers');
517544
}
518545

519546
public function tearDown() {

lib/private/Server.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -946,11 +946,7 @@ public function __construct($webRoot, \OC\Config $config) {
946946
$this->registerDeprecatedAlias('DateTimeFormatter', IDateTimeFormatter::class);
947947

948948
$this->registerService(IUserMountCache::class, function (ContainerInterface $c) {
949-
$mountCache = new UserMountCache(
950-
$c->get(IDBConnection::class),
951-
$c->get(IUserManager::class),
952-
$c->get(LoggerInterface::class)
953-
);
949+
$mountCache = $c->get(UserMountCache::class);
954950
$listener = new UserMountCacheListener($mountCache);
955951
$listener->listen($c->get(IUserManager::class));
956952
return $mountCache;
@@ -959,9 +955,7 @@ public function __construct($webRoot, \OC\Config $config) {
959955
$this->registerDeprecatedAlias('UserMountCache', IUserMountCache::class);
960956

961957
$this->registerService(IMountProviderCollection::class, function (ContainerInterface $c) {
962-
$loader = \OC\Files\Filesystem::getLoader();
963-
$mountCache = $c->get(IUserMountCache::class);
964-
$manager = new \OC\Files\Config\MountProviderCollection($loader, $mountCache);
958+
$manager = $c->get(\OC\Files\Config\MountProviderCollection::class);
965959

966960
// builtin providers
967961

tests/lib/Files/Config/UserMountCacheTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OC\Files\Storage\Storage;
1414
use OCP\Cache\CappedMemoryCache;
1515
use OC\User\Manager;
16+
use OCP\Diagnostics\IEventLogger;
1617
use OCP\EventDispatcher\IEventDispatcher;
1718
use OCP\Files\Config\ICachedMountInfo;
1819
use OCP\ICacheFactory;
@@ -67,7 +68,7 @@ protected function setUp(): void {
6768
$userBackend->createUser('u2', '');
6869
$userBackend->createUser('u3', '');
6970
$this->userManager->registerBackend($userBackend);
70-
$this->cache = new \OC\Files\Config\UserMountCache($this->connection, $this->userManager, $this->createMock(LoggerInterface::class));
71+
$this->cache = new \OC\Files\Config\UserMountCache($this->connection, $this->userManager, $this->createMock(LoggerInterface::class), $this->createMock(IEventLogger::class));
7172
}
7273

7374
protected function tearDown(): void {

0 commit comments

Comments
 (0)