Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize the check for inlined services #2339

Merged
merged 4 commits into from
Sep 29, 2020

Conversation

aschempp
Copy link
Member

Our current implementation calls $container->getRemovedIds() for every class before checking if its a singleton. This results in a lot of overhead, because $container->getRemovedIds() loads the removed IDs from file on every access. I assume that's to not memory-cache the IDs, but in our case it results in a ton of unnecessary calls.

The behavior of System::import() and System::importStatic() have slightly changed:
In debug mode, the existing behavior will remain the same. In production, we use getInstance() or try to create a new instance of the class before checking for removed IDs.

@aschempp aschempp added the bug label Sep 24, 2020
@aschempp aschempp added this to the 4.9 milestone Sep 24, 2020
@aschempp aschempp requested review from Toflar and a team September 24, 2020 11:57
@aschempp aschempp self-assigned this Sep 24, 2020
}

// Only cache the remove service IDs in debug mode
$removedIds = $container->getParameter('kernel.debug') ? (static::$removedServiceIds ?: $container->getRemovedIds()) : $container->getRemovedIds();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any debugging benefit from not caching the service IDs in debug mode for the current request?

@leofeyer
Copy link
Member

It seems that you are never setting static::$removedServiceIds. 🤔

@aschempp
Copy link
Member Author

Good catch! 😆
I updated to PR to "always cache", because in production one will always immediately get an exception when checking for the services ID, either because it was inlined or because the class does not exist/cannot be instantiated.

Copy link
Member

@leofeyer leofeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the current logic a little confusing:

if (\is_object($strClass)) {
	// Use object
}
elseif (isset(static::$arrSingletons[$strClass])) {
	// Use object
}
elseif ($container->has($strClass) && (strpos($strClass, '\\') !== false || !class_exists($strClass))) {
	// Get service
}
elseif (($container->getParameter('kernel.debug') || !class_exists($strClass)) && self::isServiceInlined($strClass)) {
	// throw ServiceNotFoundException()
}
elseif (!class_exists($strClass)) {
	// throw RuntimeException('class not found')
}

Why don't we make the "class not found" case more straight-forward?

if (\is_object($strClass)) {
	// Use object
}
elseif (isset(static::$arrSingletons[$strClass])) {
	// Use object
}
elseif ($container->has($strClass) && (strpos($strClass, '\\') !== false || !class_exists($strClass))) {
	// Get service
}
elseif (!class_exists($strClass)) {
	if (self::isServiceInlined($strClass)) {
		// throw ServiceNotFoundException()
	}

	// throw RuntimeException('class not found')
}

@aschempp
Copy link
Member Author

This would not consider the case when a class exists but the service was inlined. If I define a service for a class, I would always assume the service is used. That's why we currently check for that case first, but for performance reasons this PR changes it to only check in dev mode.

@leofeyer
Copy link
Member

but for performance reasons this PR changes it to only check in dev mode.

It apparently does more than that, because the prior condition was elseif ($container instanceof Container && isset($container->getRemovedIds()[$strClass])) and had no class_exists() check. I do not really understand what the code does now. 🤷🏻‍♂️

@leofeyer leofeyer merged commit 9d448e5 into contao:4.9 Sep 29, 2020
@leofeyer leofeyer changed the title Reduce check for inlined services Optimize the check for inlined services Oct 6, 2020
@aschempp aschempp deleted the bugfix/system-import branch October 20, 2020 06:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants