Search code examples
symfonysymfony-security

TraceableFirewallListener extremely long loading time


in one of my symfony projects I've been running into huge performance issues lately, where the performance issue seems to lay behind "Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener", precisely in the "Symfony\Component\Security\Http\Firewall\ContextListener".

Below are screenshots from my development server and the live server - server specifications are meeting the requirements and I'm absolutely sure the issue does not lie behind the server, as other projects have been running great on similiar servers.

I would appreciate any hint as to how to troubleshoot or debug this problem further, as I'm at my wits end. Symfony version is 4.0.1, updating to the latest version did not resolve the issue.

Edit: Debugging a little further using the stopwatch component lead me to the conclusion that the loading times are coming from Symfony/Bridge/Doctrine/Security/User/EntityUserProvider, method "refreshUser", line 93, call "$refreshedUser = $repository->find($id);" for the biggest part, as in 2647ms out of 2681ms. I have no clue where to go from now on, though.

Dev Dev - Performance Dev- Listeners

Live Live - Performance Live - Listeners

My Security config:

security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
    App\Entity\User:
        algorithm: bcrypt
    legacy_encoder:
        algorithm: md5
        encode_as_base64: false
        iterations: 1

providers:
    in_memory: { memory: ~ }
    db_provider:
        entity:
            class: App\Entity\User
            property: username

role_hierarchy:
    ROLE_USER_MO: ROLE_USER
    ROLE_USER_WKB: ROLE_USER

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        #pattern: ^/
        #http_basic: ~

        anonymous: ~
        provider: db_provider

        user_checker: App\Security\UserChecker

        logout:
            path: /logout
            target: /login

        form_login:
            login_path: login
            check_path: login

access_control:
    #- { path: ^/, roles: ROLE_USER }
    #- { path: ^/login, allow_if: "is_anonymous() and !is_authenticated()" }
    - { path: ^/motivwelten, roles: ROLE_USER }
    - { path: ^/services/.*, roles: ROLE_USER }
    - { path: ^/shop, roles: ROLE_USER }
    - { path: ^/shop/.*, roles: ROLE_USER }
    - { path: ^/user/.*, roles: ROLE_USER }
    - { path: ^/password-forgotten, allow_if: "is_anonymous() and !is_authenticated()" }
    - { path: ^/password-forgotten/.*, allow_if: "is_anonymous() and !is_authenticated()" }
    - { path: ^/downloads, roles: ROLE_USER }

erase_credentials: false

Solution

  • Following up on my edit on Mar 1, I'll provie the "solution" that fixed the loading times for me. I don't think this can be called a solution to the problem, as I manipulated the core code of the framework, which should probably never be done or necessary.

    I am fairly certain the problem lies in the entity structure I've built over the time, where there are several fetch=EAGER parts in the user entity, which should be avoided where possible.

    I changed the line 93 in Symfony/Bridge/Doctrine/Security/User/EntityUserProvider from

    $refreshedUser = $repository->find($id);
    

    to

    $refreshedUser = $repository->find(['id' => $id]);
    

    This reduced the loading time from 25 seconds to ~50ms and from 2.5 seconds to ~100ms on dev and live respectively.