Skip to content

Any ideas on how we could speed up ResourceClassResolver? #1068

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

Closed
soyuka opened this issue Apr 19, 2017 · 4 comments
Closed

Any ideas on how we could speed up ResourceClassResolver? #1068

soyuka opened this issue Apr 19, 2017 · 4 comments
Assignees

Comments

@soyuka
Copy link
Member

soyuka commented Apr 19, 2017

This class gets called a lot. I already speed up things by ~20% by avoiding the resourceNameCollectionFactory->create() call (quick & dirty):

    public function isResourceClass(string $type): bool
    {
        if (isset($this->arrayCache[$type])) {
            return $this->arrayCache[$type];
        }

        foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
            $this->arrayCache[$resourceClass] = true;
            if ($type === $resourceClass) {
                return true;
            }
        }

        $this->arrayCache[$type] = false;
        return false;
    }

Though, getResourceClass is still slow \o/. I'm not sure that we can find any key to cache our $value though.
I think that by removing try/catch we could improve it a bit, but this would break a lot of things (returning null instead of throwing an InvalidArgumentException). WDYT?

Any ideas appreciated!

@soyuka soyuka self-assigned this Apr 19, 2017
@backbone87
Copy link

if the slow part is the custom iterator, than maybe using ResourceMetadataFactoryInterface directly (with a special instance that is configured to "fail fast", if cache didnt hit) could help.

Or extending the ResourceNameCollectionInterface to have a "contains" method.

@soyuka
Copy link
Member Author

soyuka commented Apr 20, 2017

I think the slow part is getResourceClass. Or, it's not that slow but it gets called a lot: Blackfire

@soyuka
Copy link
Member Author

soyuka commented Jun 14, 2017

Closing this because I'm not sure we can do anything about that. #212

@soyuka soyuka closed this as completed Jun 14, 2017
@bastnic
Copy link
Contributor

bastnic commented Dec 19, 2019

I'm allowing myself to reopen it because ResourceClassResolver::getResourceClass is responsible of no less than 13% in prod mode, because foreach entity, it will go through ALL possible resource, without any break in the loop (seems logic) nor any cache. And so, is_a is called 63630 times.

Just adding a local cache clear everything:

        if (isset($this->localMostSpecificResourceClassCache[$targetClass])) {
            return $this->localMostSpecificResourceClassCache[$targetClass];
        }

        foreach ($this->resourceNameCollectionFactory->create() as $resourceClassName) {
            if (!is_a($targetClass, $resourceClassName, true)) {
                continue;
            }

            if (null === $mostSpecificResourceClass || is_subclass_of($resourceClassName, $mostSpecificResourceClass)) {
                $mostSpecificResourceClass = $resourceClassName;
            }
        }

        if (null === $mostSpecificResourceClass) {
            throw new \LogicException('Unexpected execution flow.');
        }

        $this->localMostSpecificResourceClassCache[$targetClass] = $mostSpecificResourceClass;

Before :

image

Diff :

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants