feat: Improve init a bit, and add more profiling steps

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
pull/52667/head
Côme Chilliet 5 months ago
parent 56897b6f3c
commit 20c6d1a7e9
No known key found for this signature in database
GPG Key ID: A3E2F658B28C760A
  1. 1
      build/rector.php
  2. 12
      lib/autoloader.php
  3. 7
      lib/base.php
  4. 4
      lib/private/AppFramework/Bootstrap/Coordinator.php
  5. 8
      lib/private/AppFramework/Utility/SimpleContainer.php
  6. 10
      lib/private/Route/Router.php
  7. 23
      lib/private/ServerContainer.php
  8. 23
      status.php

@ -52,6 +52,7 @@ class NextcloudNamespaceSkipVoter implements ClassNameImportSkipVoterInterface {
$config = RectorConfig::configure() $config = RectorConfig::configure()
->withPaths([ ->withPaths([
$nextcloudDir . '/apps', $nextcloudDir . '/apps',
$nextcloudDir . '/status.php',
// $nextcloudDir . '/config', // $nextcloudDir . '/config',
// $nextcloudDir . '/core', // $nextcloudDir . '/core',
// $nextcloudDir . '/lib', // $nextcloudDir . '/lib',

@ -22,10 +22,8 @@ class Autoloader {
/** /**
* Optional low-latency memory cache for class to path mapping. * Optional low-latency memory cache for class to path mapping.
*
* @var \OC\Memcache\Cache
*/ */
protected $memoryCache; protected ?ICache $memoryCache = null;
/** /**
* Autoloader constructor. * Autoloader constructor.
@ -127,15 +125,15 @@ class Autoloader {
* @throws AutoloadNotAllowedException * @throws AutoloadNotAllowedException
*/ */
public function load(string $class): bool { public function load(string $class): bool {
if (class_exists($class, false)) {
return false;
}
$pathsToRequire = null; $pathsToRequire = null;
if ($this->memoryCache) { if ($this->memoryCache) {
$pathsToRequire = $this->memoryCache->get($class); $pathsToRequire = $this->memoryCache->get($class);
} }
if (class_exists($class, false)) {
return false;
}
if (!is_array($pathsToRequire)) { if (!is_array($pathsToRequire)) {
// No cache or cache miss // No cache or cache miss
$pathsToRequire = []; $pathsToRequire = [];

@ -188,8 +188,6 @@ class OC {
} }
public static function checkConfig(): void { public static function checkConfig(): void {
$l = Server::get(\OCP\L10N\IFactory::class)->get('lib');
// Create config if it does not already exist // Create config if it does not already exist
$configFilePath = self::$configDir . '/config.php'; $configFilePath = self::$configDir . '/config.php';
if (!file_exists($configFilePath)) { if (!file_exists($configFilePath)) {
@ -201,6 +199,7 @@ class OC {
if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled() if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
|| !$configFileWritable && \OCP\Util::needUpgrade()) { || !$configFileWritable && \OCP\Util::needUpgrade()) {
$urlGenerator = Server::get(IURLGenerator::class); $urlGenerator = Server::get(IURLGenerator::class);
$l = Server::get(\OCP\L10N\IFactory::class)->get('lib');
if (self::$CLI) { if (self::$CLI) {
echo $l->t('Cannot write into "config" directory!') . "\n"; echo $l->t('Cannot write into "config" directory!') . "\n";
@ -711,6 +710,7 @@ class OC {
self::performSameSiteCookieProtection($config); self::performSameSiteCookieProtection($config);
if (!defined('OC_CONSOLE')) { if (!defined('OC_CONSOLE')) {
$eventLogger->start('check_server', 'Run a few configuration checks');
$errors = OC_Util::checkServer($systemConfig); $errors = OC_Util::checkServer($systemConfig);
if (count($errors) > 0) { if (count($errors) > 0) {
if (!self::$CLI) { if (!self::$CLI) {
@ -745,6 +745,7 @@ class OC {
} elseif (self::$CLI && $config->getSystemValueBool('installed', false)) { } elseif (self::$CLI && $config->getSystemValueBool('installed', false)) {
$config->deleteAppValue('core', 'cronErrors'); $config->deleteAppValue('core', 'cronErrors');
} }
$eventLogger->end('check_server');
} }
// User and Groups // User and Groups
@ -752,6 +753,7 @@ class OC {
self::$server->getSession()->set('user_id', ''); self::$server->getSession()->set('user_id', '');
} }
$eventLogger->start('setup_backends', 'Setup group and user backends');
Server::get(\OCP\IUserManager::class)->registerBackend(new \OC\User\Database()); Server::get(\OCP\IUserManager::class)->registerBackend(new \OC\User\Database());
Server::get(\OCP\IGroupManager::class)->addBackend(new \OC\Group\Database()); Server::get(\OCP\IGroupManager::class)->addBackend(new \OC\Group\Database());
@ -770,6 +772,7 @@ class OC {
// Run upgrades in incognito mode // Run upgrades in incognito mode
OC_User::setIncognitoMode(true); OC_User::setIncognitoMode(true);
} }
$eventLogger->end('setup_backends');
self::registerCleanupHooks($systemConfig); self::registerCleanupHooks($systemConfig);
self::registerShareHooks($systemConfig); self::registerShareHooks($systemConfig);

@ -83,10 +83,10 @@ class Coordinator {
$appNameSpace = App::buildAppNamespace($appId); $appNameSpace = App::buildAppNamespace($appId);
$applicationClassName = $appNameSpace . '\\AppInfo\\Application'; $applicationClassName = $appNameSpace . '\\AppInfo\\Application';
try { try {
if (class_exists($applicationClassName) && in_array(IBootstrap::class, class_implements($applicationClassName), true)) { if (class_exists($applicationClassName) && is_a($applicationClassName, IBootstrap::class, true)) {
$this->eventLogger->start("bootstrap:register_app:$appId:application", "Load `Application` instance for $appId"); $this->eventLogger->start("bootstrap:register_app:$appId:application", "Load `Application` instance for $appId");
try { try {
/** @var IBootstrap|App $application */ /** @var IBootstrap&App $application */
$apps[$appId] = $application = $this->serverContainer->query($applicationClassName); $apps[$appId] = $application = $this->serverContainer->query($applicationClassName);
} catch (QueryException $e) { } catch (QueryException $e) {
// Weird, but ok // Weird, but ok

@ -153,13 +153,13 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
return $closure($this); return $closure($this);
}; };
$name = $this->sanitizeName($name); $name = $this->sanitizeName($name);
if (isset($this[$name])) { if (isset($this->container[$name])) {
unset($this[$name]); unset($this->container[$name]);
} }
if ($shared) { if ($shared) {
$this[$name] = $wrapped; $this->container[$name] = $wrapped;
} else { } else {
$this[$name] = $this->container->factory($wrapped); $this->container[$name] = $this->container->factory($wrapped);
} }
} }

@ -54,9 +54,9 @@ class Router implements IRouter {
protected LoggerInterface $logger, protected LoggerInterface $logger,
IRequest $request, IRequest $request,
private IConfig $config, private IConfig $config,
private IEventLogger $eventLogger, protected IEventLogger $eventLogger,
private ContainerInterface $container, private ContainerInterface $container,
private IAppManager $appManager, protected IAppManager $appManager,
) { ) {
$baseUrl = \OC::$WEBROOT; $baseUrl = \OC::$WEBROOT;
if (!($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) { if (!($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
@ -116,9 +116,11 @@ class Router implements IRouter {
$this->loaded = true; $this->loaded = true;
$routingFiles = $this->getRoutingFiles(); $routingFiles = $this->getRoutingFiles();
$this->eventLogger->start('route:load:attributes', 'Loading Routes from attributes');
foreach (\OC_App::getEnabledApps() as $enabledApp) { foreach (\OC_App::getEnabledApps() as $enabledApp) {
$this->loadAttributeRoutes($enabledApp); $this->loadAttributeRoutes($enabledApp);
} }
$this->eventLogger->end('route:load:attributes');
} else { } else {
if (isset($this->loadedApps[$app])) { if (isset($this->loadedApps[$app])) {
return; return;
@ -140,6 +142,7 @@ class Router implements IRouter {
} }
} }
$this->eventLogger->start('route:load:files', 'Loading Routes from files');
foreach ($routingFiles as $app => $file) { foreach ($routingFiles as $app => $file) {
if (!isset($this->loadedApps[$app])) { if (!isset($this->loadedApps[$app])) {
if (!$this->appManager->isAppLoaded($app)) { if (!$this->appManager->isAppLoaded($app)) {
@ -160,6 +163,7 @@ class Router implements IRouter {
$this->root->addCollection($collection); $this->root->addCollection($collection);
} }
} }
$this->eventLogger->end('route:load:files');
if (!isset($this->loadedApps['core'])) { if (!isset($this->loadedApps['core'])) {
$this->loadedApps['core'] = true; $this->loadedApps['core'] = true;
@ -265,6 +269,7 @@ class Router implements IRouter {
$this->loadRoutes(); $this->loadRoutes();
} }
$this->eventLogger->start('route:url:match', 'Symfony url matcher call');
$matcher = new UrlMatcher($this->root, $this->context); $matcher = new UrlMatcher($this->root, $this->context);
try { try {
$parameters = $matcher->match($url); $parameters = $matcher->match($url);
@ -283,6 +288,7 @@ class Router implements IRouter {
throw $e; throw $e;
} }
} }
$this->eventLogger->end('route:url:match');
$this->eventLogger->end('route:match'); $this->eventLogger->end('route:match');
return $parameters; return $parameters;

@ -128,18 +128,17 @@ class ServerContainer extends SimpleContainer {
} catch (QueryException $e) { } catch (QueryException $e) {
// Continue with general autoloading then // Continue with general autoloading then
} }
} // In case the service starts with OCA\ we try to find the service in
// the apps container first.
// In case the service starts with OCA\ we try to find the service in if (($appContainer = $this->getAppContainerForService($name)) !== null) {
// the apps container first. try {
if (($appContainer = $this->getAppContainerForService($name)) !== null) { return $appContainer->queryNoFallback($name);
try { } catch (QueryException $e) {
return $appContainer->queryNoFallback($name); // Didn't find the service or the respective app container
} catch (QueryException $e) { // In this case the service won't be part of the core container,
// Didn't find the service or the respective app container // so we can throw directly
// In this case the service won't be part of the core container, throw $e;
// so we can throw directly }
throw $e;
} }
} elseif (str_starts_with($name, 'OC\\Settings\\') && substr_count($name, '\\') >= 3) { } elseif (str_starts_with($name, 'OC\\Settings\\') && substr_count($name, '\\') >= 3) {
$segments = explode('\\', $name); $segments = explode('\\', $name);

@ -1,33 +1,42 @@
<?php <?php
declare(strict_types=1);
/** /**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
require_once __DIR__ . '/lib/versioncheck.php'; require_once __DIR__ . '/lib/versioncheck.php';
use OC\SystemConfig;
use OCP\Defaults;
use OCP\Server;
use OCP\ServerVersion;
use OCP\Util;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
try { try {
require_once __DIR__ . '/lib/base.php'; require_once __DIR__ . '/lib/base.php';
$systemConfig = \OC::$server->getSystemConfig(); $systemConfig = Server::get(SystemConfig::class);
$installed = (bool)$systemConfig->getValue('installed', false); $installed = (bool)$systemConfig->getValue('installed', false);
$maintenance = (bool)$systemConfig->getValue('maintenance', false); $maintenance = (bool)$systemConfig->getValue('maintenance', false);
# see core/lib/private/legacy/defaults.php and core/themes/example/defaults.php # see core/lib/private/legacy/defaults.php and core/themes/example/defaults.php
# for description and defaults # for description and defaults
$defaults = new \OCP\Defaults(); $defaults = new Defaults();
$serverVersion = Server::get(ServerVersion::class);
$values = [ $values = [
'installed' => $installed, 'installed' => $installed,
'maintenance' => $maintenance, 'maintenance' => $maintenance,
'needsDbUpgrade' => \OCP\Util::needUpgrade(), 'needsDbUpgrade' => Util::needUpgrade(),
'version' => implode('.', \OCP\Util::getVersion()), 'version' => implode('.', $serverVersion->getVersion()),
'versionstring' => \OCP\Server::get(\OCP\ServerVersion::class)->getVersionString(), 'versionstring' => $serverVersion->getVersionString(),
'edition' => '', 'edition' => '',
'productname' => $defaults->getProductName(), 'productname' => $defaults->getProductName(),
'extendedSupport' => \OCP\Util::hasExtendedSupport() 'extendedSupport' => Util::hasExtendedSupport()
]; ];
if (OC::$CLI) { if (OC::$CLI) {
print_r($values); print_r($values);
@ -38,5 +47,5 @@ try {
} }
} catch (Exception $ex) { } catch (Exception $ex) {
http_response_code(500); http_response_code(500);
\OCP\Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'remote','exception' => $ex]); Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'remote','exception' => $ex]);
} }

Loading…
Cancel
Save