Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Some ideas to improve performance of the Translator component #13948

Copy link
Copy link
Closed
@javiereguiluz

Description

@javiereguiluz
Issue body actions

The problem

Recently some people have raised concerns about Translator component performance (see #13676 for example). I was inspecting the dumped container for production environment to get more information about this component and I saw the following problems:

1. All translation loaders and dumpers are instantiated and loaded, no matter which ones you use:

protected function getTranslation_LoaderService()
{
    $a = $this->get('translation.loader.xliff');
    $this->services['translation.loader'] = $instance = new \Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader();
    $instance->addLoader('php', $this->get('translation.loader.php'));
    $instance->addLoader('yml', $this->get('translation.loader.yml'));
    $instance->addLoader('xlf', $a);
    $instance->addLoader('xliff', $a);
    $instance->addLoader('po', $this->get('translation.loader.po'));
    $instance->addLoader('mo', $this->get('translation.loader.mo'));
    $instance->addLoader('ts', $this->get('translation.loader.qt'));
    $instance->addLoader('csv', $this->get('translation.loader.csv'));
    $instance->addLoader('res', $this->get('translation.loader.res'));
    $instance->addLoader('dat', $this->get('translation.loader.dat'));
    $instance->addLoader('ini', $this->get('translation.loader.ini'));
    $instance->addLoader('json', $this->get('translation.loader.json'));
    return $instance;
}

protected function getTranslation_Dumper_QtService()
{
    return $this->services['translation.dumper.qt'] = new \Symfony\Component\Translation\Dumper\QtFileDumper();
}

protected function getTranslation_Dumper_ResService()
{
    return $this->services['translation.dumper.res'] = new \Symfony\Component\Translation\Dumper\IcuResFileDumper();
}

// ...

Same thing happens with the translation dumpers:

protected function getTranslation_WriterService()
{
    $this->services['translation.writer'] = $instance = new \Symfony\Component\Translation\Writer\TranslationWriter();
    $instance->addDumper('php', $this->get('translation.dumper.php'));
    $instance->addDumper('xlf', $this->get('translation.dumper.xliff'));
    $instance->addDumper('po', $this->get('translation.dumper.po'));
    $instance->addDumper('mo', $this->get('translation.dumper.mo'));
    $instance->addDumper('yml', $this->get('translation.dumper.yml'));
    $instance->addDumper('ts', $this->get('translation.dumper.qt'));
    $instance->addDumper('csv', $this->get('translation.dumper.csv'));
    $instance->addDumper('ini', $this->get('translation.dumper.ini'));
    $instance->addDumper('json', $this->get('translation.dumper.json'));
    $instance->addDumper('res', $this->get('translation.dumper.res'));
    return $instance;
}

2. All resources for all locales are loaded, no matter which ones you use:

protected function getTranslator_DefaultService()
{
    // ...

    $instance->setFallbackLocales(array(0 => 'es'));
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf'), 'af', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf'), 'ar', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf'), 'az', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf'), 'bg', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf'), 'ca', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf'), 'cs', 'validators');
    $instance->addResource('xlf', ($this->targetDirs[3].'/vendor/symfony/symfony/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf'), 'cy', 'validators');
    // ... hundreds of additional lines
}

The solution

1. We could solve this problem with a technique similar to the templating engines selector:

framework:
    # ...
    templating:
        engines: ['twig', 'php']

In the case of translator:

framework:
    # ...
    translator:
        loaders: ['yml', 'xliff']
        dumpers: ['php']

To maintain backwards compatibility, these options could be null by default, meaning that all loaders/dumpers should be loaded.

2. We could solve this problem defining a new active_locales option to explicitly define the list of locales which will be used in the application:

framework:
    # ...
    default_locale: 'en'
    active_locales: ['es', 'en', 'fr', 'de']

Again, to maintain backwards compatibility, this new option would default to null to load all resources for all locales.

The benchmark

In my tests, I modified the generated container commenting/removing the lines that instantiate all the unused loaders/dumpers and I also removed all the translation resources files except the ones for the active locale. A quick before/after comparison made with Blackfire gave me around 10% performance increase in CPU time, 2.64% memory consumption reduction and about 600 less PHP function calls.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.