Project

General

Profile

Actions

Bug #106822

open

LanguagePackService::getExtensionLanguagePackDetails() causes major performance issues due to Finder usage and file counting

Added by Kerem Koc 15 days ago.

Status:
New
Priority:
Should have
Assignee:
-
Category:
Language Manager (backend)
Target version:
-
Start date:
2025-06-04
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
12
PHP Version:
8.2
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

In TYPO3 v12.4, we’ve identified a serious performance bottleneck in the method LanguagePackService::getExtensionLanguagePackDetails()

💥 Problem:

The current implementation performs expensive and repeated filesystem scans using Symfony's Finder component. Specifically:
1. Unnecessary file counting

$files = $finder->files()->in($path . 'Resources/Private/Language/')->name('*.xlf');
if ($files->count() === 0) {
    continue;
}
$files->count() iterates through all matching files just to check if there’s at least one. This results in tens of thousands of unnecessary file operations when only a boolean check is needed.

✅ Suggestion: Replace with hasResults() (available since Symfony Finder 5.4):

if (!$files->hasResults()) {
    continue;
}

2. Repeated Finder instantiation and recursion


    The Symfony Finder is instantiated and executed once per extension.

    With each call, RecursiveDirectoryIterator and related filesystem iterators are invoked.

    In our profiling, this led to 134,000+ calls to RecursiveDirectoryIterator::current() across requests.

    This is amplified when 20+ languages are configured in EXTCONF['lang']['availableLanguages'].

$packageManager = GeneralUtility::makeInstance(PackageManager::class);
$activePackages = $packageManager->getActivePackages();
foreach ($activePackages as $package) {
    $finder = new Finder();
    $files = $finder->files()->in($path . 'Resources/Private/Language/')->name('*.xlf');
}

📉 Result: Extremely high I/O and CPU cost even for extensions with no translation files.
🧪 Our setup (example):

'EXTCONF' => [
    'lang' => [
        'availableLanguages' => [
            'ar', 'bg', 'cs', 'de', 'es', 'fr', 'hu', 'it', 'ja', 'ko',
            'lt', 'nl', 'pl', 'pt', 'pt_BR', 'ro', 'ru', 'sk', 'tr',
            'uk', 'vi', 'zh', 'zh_HK',
        ],
    ],
],

📊 Observed impact:

Over 120,000 Finder iterations during a single languagePackDownload() cycle.
134,000+ calls to RecursiveDirectoryIterator::current() (measured via profiling tools).
Significant performance degradation during Extension Manager operations, language pack processing, and installs.

Recommendation:

Replace $files->count() === 0 with !$files->hasResults()
Avoid creating a new Finder instance per package — consider memorization or shared reuse if feasible

No data to display

Actions

Also available in: Atom PDF