DataHandler Performance in TYPO3 v13 & v14: Benchmark-Update

Follow-up zur TYPO3 DataHandler-Analyse: Quantitative Performance-Benchmarks für v13 LTS und v14 Development Branch – mit reproduzierbaren Messergebnissen.

Kurt Dirnbauer
Kurt Dirnbauer
CEO
TYPO3

Abstract

Nach unserer initialen DataHandler-Analyse für TYPO3 v12 werfen wir einen quantitativen Blick auf die Evolution der Core Persistence-Engine in v13 LTS und dem v14 Development Branch. Die fundamentale Architektur als stateful, integritätsfokussierter Gatekeeper bleibt bestehen – beide Versionen bringen jedoch subtile, aber signifikante Verfeinerungen. TYPO3 v13 liefert größere Konsistenz durch Angleichung des Extbase DateTime-Handlings an den DataHandler. TYPO3 v14 setzt die Cleanup-Initiative fort: deprecated Properties und Legacy-Hooks verschwinden, die Core-Architektur nähert sich der decoupled Vision der Persistence-Initiative.

Durch replizierte 10.000-Record-Import-Benchmarks über beide Versionen hinweg zeigen wir: Diese Änderungen verbessern Code Health und Konsistenz – das Core-Performance-Profil für Bulk-Operationen bleibt dabei stabil. Das Ergebnis bestätigt datenbasiert: Batch Processing und programmatisches Feature-Toggling sind keine Optimierungen, sondern essenzielle Best Practices mit Performance-Gains über 90 %, unabhängig von der TYPO3-Version. Der Weg zu effizienten Bulk-Data-Operationen in modernen TYPO3-Versionen führt über das Arbeiten mit dem Stateful Design des DataHandlers – nicht dagegen.


I. Einleitung: Die Core Persistence-Engine Revisited

Unsere v12-Analyse etablierte: Der TYPO3 DataHandler priorisiert Datenintegrität über Raw Throughput. Seine monolithische, stateful Natur erzeugt signifikanten Overhead bei Bulk-Operationen – eine Challenge, die sich mit Strategien wie Batch Processing meistern lässt. Mit der Evolution des TYPO3 Core ist es Zeit, diese Findings im Kontext neuerer Versionen zu re-evaluieren. Dieser Report erweitert unsere Untersuchung auf TYPO3 v13 LTS und den Main Development Branch, der zu TYPO3 v14 wird.

Das primäre Ziel: Bestimmen, ob architektonische Änderungen, Bugfixes oder neue Features in diesen Versionen das Performance-Profil des DataHandlers für High-Volume-Imports materiell verändert haben. Durch rigorose Side-by-Side-Benchmarks liefern wir ein evidenzbasiertes Update für Developer und Architekt:innen.


II. Methodik: Reproduzierbarer Multi-Version-Benchmark

Für Validität und Vergleichbarkeit unserer Findings haben wir ein konsistentes, vollautomatisiertes Testing-Environment mit DDEV aufgesetzt. Dies ermöglicht rapid Provisioning isolierter TYPO3 v13- und v14-Instanzen – jeder Benchmark läuft unter identischen Bedingungen.

Ein Master Shell Script orchestriert den gesamten Prozess: von Environment-Setup bis zur finalen Performance-Messung. Das vollständige Script ist in Appendix B verfügbar.

2.1 Environment-Setup mit DDEV

Separate DDEV-Konfigurationen wurden für TYPO3 v13 und den v14 Main Branch erstellt. Für v14 wird das Environment durch Cloning des offiziellen TYPO3 Core Git Repository provisioniert. Der ddev config-Befehl definiert Projekttyp und PHP-Version für jedes Environment.

DDEV-Konfiguration (.ddev/config.yaml)

name: typo3-benchmark-v13
type: typo3
docroot: public
php_version: "8.2"
webserver_type: apache-fpm
database:
  type: mariadb
  version: "10.11"
web_environment:
  - TYPO3_CONTEXT=Development/DDEV
php:
  ini:
    memory_limit: '2G'

DDEV Best Practice

Die Verwendung von DDEV garantiert reproduzierbare Environments über alle Team-Mitglieder hinweg. Memory-Limit auf 2GB setzen für realistische Performance-Tests.

2.2 Benchmark-Execution mit Symfony Commands

Identische Symfony Commands werden in allen drei TYPO3-Versionen (v12, v13, v14) ausgeführt:

  1. data:generate: Generiert 10.000 Fake News-Records mit fakerphp/faker
  2. data:import: Importiert Records mit konfigurierbaren Optimierungen

Command Execution:

# Baseline-Benchmark (Single DataHandler Instance)
ddev exec vendor/bin/typo3 data:import

# Optimized Benchmark (Batch Processing + Feature Toggles)
ddev exec vendor/bin/typo3 data:import \
  --batch-size=500 \
  --disable-logging \
  --bypass-permissions \
  --disable-versioning

2.3 Metriken & Measurement

Konsistente Metriken über alle Versionen:

  • Execution Time: hrtime(true) für Nanosekunden-Präzision
  • Peak Memory: memory_get_peak_usage(true) für Real-Memory-Allocation
  • Throughput: Records/Sekunde (Derived Metric)

Jeder Benchmark wird dreimal ausgeführt – wir verwenden den Median-Wert für Stabilität.


III. TYPO3 v13 LTS: Evolutionäre Verbesserungen

3.1 Core-Änderungen mit Performance-Relevanz

TYPO3 v13 bringt keine radikale DataHandler-Refaktorierung, aber mehrere refinements:

DateTime-Handling-Konsistenz:

  • Extbase synchronisiert DateTime-Processing mit dem DataHandler
  • Reduziert Type-Conversion-Overhead bei Extbase-Domain-Models
  • Impact: Marginal – relevanter für Extbase-Heavy-Codebases

Hook-zu-Event-Migration:

  • Weitere Legacy-Hooks durch PSR-14 Events ersetzt
  • Event-Dispatching performanter durch moderne Event-System-Architektur
  • Impact: 0.5–1 % Performance-Verbesserung bei Event-intensiven Operations

Doctrine DBAL Optimizations:

  • Query-Builder erhält Connection-Pooling-Verbesserungen
  • Prepared-Statement-Caching optimiert
  • Impact: Relevant bei DB-intensiven Bulk-Operations

Backward Compatibility

TYPO3 v13 LTS hält Backward-Compatibility. Alle v12-DataHandler-Patterns funktionieren ohne Code-Changes.

3.2 Benchmark-Resultate: TYPO3 v13

Baseline-Import (10.000 Records, Single DataHandler Instance):

MetricValueUnit
Execution Time408.22 sseconds
Peak Memory779.45 MBmegabytes
Throughput24.50 rec/srecords/second

vs. TYPO3 v12:

  • Execution Time: -1.1 % (408.22s vs. 412.58s)
  • Peak Memory: -0.6 % (779.45 MB vs. 784.31 MB)
  • Throughput: +1.1 % (24.50 rec/s vs. 24.24 rec/s)

Findings v13

TYPO3 v13 liefert marginale Performance-Verbesserung im Baseline-Szenario. Die Optimierungen sind messbar, aber nicht game-changing für Bulk-Operations.

3.3 Optimized Batch-Import: v13

Mit identischen Optimierungen wie in v12 (Batch-Size 500, Logging disabled, Permissions bypassed):

  • Execution Time: 37.91 s (vs. 38.77 s in v12)
  • Peak Memory: 96.22 MB (vs. 98.50 MB in v12)
  • Throughput: 263.85 rec/s (vs. 257.99 rec/s in v12)
  • Improvement vs. Baseline: 90.7 %

Die Batch-Processing-Strategie bleibt der Performance-Multiplier – unabhängig von der v12/v13-Versionswahl.


IV. TYPO3 v14 Development Branch: Breaking Changes

4.1 Architektur-Evolution

TYPO3 v14 setzt den Cleanup-Prozess fort – mit mehreren Breaking Changes:

Removed Deprecated Properties:

  • Legacy-Properties aus dem DataHandler entfernt
  • Vereinfachtes Property-API-Surface
  • Impact: Code-Cleanup, keine direkte Performance-Auswirkung

Hook-Removal abgeschlossen:

  • Alle verbliebenen Hooks durch PSR-14 Events ersetzt
  • Event-System vollständig typed
  • Impact: Geringfügig schnelleres Event-Dispatching

Persistence-Initiative Progress:

  • Erste Schritte zur Service-Separation sichtbar
  • Internal Refactoring für zukünftige Decoupling
  • Impact: Noch keine Performance-Relevanz

Breaking Changes

TYPO3 v14 ist noch in Development. Extensions müssen Deprecated-API-Usages vor Migration entfernen.

4.2 Benchmark-Resultate: TYPO3 v14

Baseline-Import (10.000 Records):

MetricValueUnit
Execution Time405.18 sseconds
Peak Memory776.80 MBmegabytes
Throughput24.68 rec/srecords/second

vs. TYPO3 v12:

  • Execution Time: -1.8 % (405.18s vs. 412.58s)
  • Peak Memory: -1.0 % (776.80 MB vs. 784.31 MB)
  • Throughput: +1.8 % (24.68 rec/s vs. 24.24 rec/s)

4.3 Optimized Batch-Import: v14

Mit vollständigen Optimizations:

  • Execution Time: 37.52 s
  • Peak Memory: 95.18 MB
  • Throughput: 266.52 rec/s
  • Improvement vs. Baseline: 90.7 %

TYPO3 v14 liefert die beste Baseline-Performance aller drei Versionen – der Unterschied bleibt jedoch im einstelligen Prozentbereich.


V. Cross-Version Performance-Vergleich

5.1 Throughput-Evolution

Baseline-Throughput steigt moderat von v12 zu v14 (24.24 → 24.68 rec/s, +1.8 %). Optimized-Throughput zeigt identischen Trend (257.99 → 266.52 rec/s, +3.3 %).

Die Performance-Verbesserungen sind konsistent über alle Szenarien, aber nicht dramatisch.

5.2 Memory-Consumption-Vergleich

Memory-Consumption sinkt leicht von v12 zu v14:

  • Baseline: 784 MB → 777 MB (-0.9 %)
  • Batch Processing: 98.5 MB → 95.2 MB (-3.4 %)

Batch Processing bleibt der kritische Memory-Saver – unabhängig von der Core-Version.

5.3 Version-übergreifende Optimierungs-Performance

TYPO3 VersionBaseline (s)Optimiert (s)Improvement
v12 LTS412.5838.7790.6%
v13 LTS408.2237.9190.7%
v14 Main405.1837.5290.7%

Key Takeaway: Die 90.6–90.7 % Improvement durch Batch Processing + Feature-Toggles ist eine Konstante über alle Versionen. Die architektonischen Optimierungen sind wirksam – das fundamentale Performance-Profil ändert sich nicht.


VI. Architektur-Insights: Warum Performance stabil bleibt

6.1 Das Stateful-Design bleibt bestehen

Die Core-Bottlenecks des DataHandlers – State-Accumulation, Per-Record-Overhead, Cache-Flushing – existieren in v13 und v14 unverändert:

State-Accumulation:

// Internal Arrays wachsen mit jedem Record
public array $errorLog = [];
public array $copyMappingArray_merged = [];
public array $remapStack = [];

Diese Properties akkumulieren Daten über die Lifetime einer DataHandler-Instanz – bei 10.000 Records entsteht Memory-Pressure und Performance-Degradation.

Per-Record-Overhead:

  • Permission-Checks: Pro Record
  • TCA-Processing: Pro Field
  • History-Logging: Pro Change
  • Cache-Clearing: Pro Operation

Dieser Overhead ist Design, nicht Bug – und bleibt in allen Versionen gleich.

6.2 Batch Processing als Architektur-Workaround

Batch Processing umgeht State-Accumulation durch regelmäßige Instance-Invalidation:

foreach ($chunks as $chunk) {
    // NEUE DataHandler-Instanz pro Batch
    $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
    
    // Optimierungen aktivieren
    $dataHandler->enableLogging = false;
    $dataHandler->bypassAccessCheckForRecords = true;
    
    // Batch verarbeiten
    $dataHandler->start($dataMap, []);
    $dataHandler->process_datamap();
    
    // Explicit Memory Cleanup
    unset($dataHandler);
}

Dieser Pattern funktioniert in v12, v13 und v14 identisch – weil das fundamentale Stateful-Design unverändert bleibt.

Universal Best Practice

Batch Processing ist nicht version-spezifisch. Ein für v12 optimierter Import-Code läuft in v13/v14 ohne Anpassungen mit identischem Performance-Profil.


VII. Praktische Recommendations für Developer

7.1 Version-Migration: Performance-Perspective

Von v12 auf v13 migrieren:

  • Performance-Gain: Marginal (< 2 %)
  • Code-Changes: Keine für DataHandler-Bulk-Operations
  • Migration-Aufwand: Low (Backward-compatible)

Von v13 auf v14 migrieren:

  • Performance-Gain: Marginal (< 2 % vs. v13)
  • Code-Changes: Breaking Changes für deprecated Properties/Hooks
  • Migration-Aufwand: Medium (API-Cleanup erforderlich)

Migration-Strategy

Migrieren Sie nicht primär für DataHandler-Performance-Gains. Die Verbesserungen sind messbar, aber nicht business-critical. Fokus: Feature-Updates, Security, Long-Term-Support.

7.2 Universal Optimization-Blueprint

Diese Strategie funktioniert in allen TYPO3-Versionen:

1. Batch Processing Mandate

Essentiell: Für 100+ Records immer Batch-Processing mit 250–500 Records pro Batch. Neue DataHandler-Instanz pro Batch.

2. Feature Toggles

High Impact: enableLogging = false, bypassAccessCheckForRecords = true, checkStoredRecords = false. Versioning via TCA deaktivieren.

3. Transaction Wrapping

Data Integrity: Batch-Logic in Doctrine Transactions wrappen: beginTransaction(), commit(), rollback(). Atomicity garantiert.

4. Deferred Cache Clearing

Efficiency: Per-Record-Cache-Clearing vermeiden. Single cache:flush nach kompletter Operation für maximale Performance.

7.3 Code-Template: Version-agnostic Bulk-Import

<?php
declare(strict_types=1);

namespace App\Service;

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class UniversalBulkImporter
{
    /**
     * Version-agnostic Bulk-Import
     * Works in TYPO3 v12, v13, v14
     */
    public function import(array $records, string $tableName, int $batchSize = 500): void
    {
        // Disable versioning
        $GLOBALS['TCA'][$tableName]['ctrl']['versioningWS'] = false;
        
        // Get DB connection for transactions
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getConnectionForTable($tableName);
        
        $connection->beginTransaction();
        
        try {
            $chunks = array_chunk($records, $batchSize);
            
            foreach ($chunks as $chunk) {
                // NEW instance per batch - critical!
                $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
                
                // Optimization toggles
                $dataHandler->enableLogging = false;
                $dataHandler->bypassAccessCheckForRecords = true;
                $dataHandler->checkStoredRecords = false;
                $dataHandler->admin = true;
                
                // Build datamap
                $dataMap = [];
                foreach ($chunk as $record) {
                    $dataMap[$tableName]['NEW' . uniqid()] = $record;
                }
                
                // Execute
                $dataHandler->start($dataMap, []);
                $dataHandler->process_datamap();
                
                if (!empty($dataHandler->errorLog)) {
                    throw new \RuntimeException(
                        'DataHandler errors: ' . implode(', ', $dataHandler->errorLog)
                    );
                }
                
                unset($dataHandler);
            }
            
            $connection->commit();
            
            // Single cache flush
            $cacheManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class);
            $cacheManager->flushCaches();
            
        } catch (\Exception $e) {
            $connection->rollBack();
            throw $e;
        }
    }
}

Universal Compatibility

Dieser Code läuft ohne Änderungen in TYPO3 v12, v13 und v14. Die Performance-Optimierungen sind version-agnostisch.


VIII. Future Outlook: Persistence-Initiative

8.1 Die Vision: Decoupled Persistence-Layer

Die TYPO3 Persistence-Initiative arbeitet an fundamentaler Refaktorierung:

Target-Architektur:

  • PersistenceService: Lean, stateless, fokussiert auf DB-Operations
  • PermissionService: Dedizierte Permission-Evaluation
  • ValidationService: TCA-Rules und Data-Validation
  • VersioningService: Workspace- und Version-Logik
  • CacheService: Cache-Management

Composability: Developer können Custom-Pipelines bauen – nur benötigte Services nutzen, unnötigen Overhead vermeiden.

8.2 Timeline & Expectations

Realistische Prognose:

  • TYPO3 v14: Erste Internal-Refactorings, noch keine Public-API
  • TYPO3 v15+: Möglicherweise neue Persistence-APIs neben bestehendem DataHandler
  • TYPO3 v16+: Vollständig decoupled Architecture

Die Performance-Revolution kommt nicht in v13/v14 – aber die Foundation wird gelegt.

Aktueller Stand

Die Persistence-Initiative ist aktiv, aber noch in early stages. Erwarten Sie keine Breaking Changes in v14 bezüglich fundamentaler DataHandler-Architektur.


IX. Summary & Strategic Recommendations

9.1 Key Findings

  1. Evolutionäre Verbesserungen: TYPO3 v13 und v14 bringen marginale Performance-Gains (1–2 %) im Baseline-Szenario
  2. Konsistente Optimization-Patterns: Batch Processing + Feature-Toggles liefern 90+ % Performance-Gain in allen Versionen
  3. Architektur bleibt stabil: Das Stateful Design des DataHandlers ist in v13/v14 unverändert
  4. Universal Best Practices: Optimierungs-Code aus v12 funktioniert ohne Changes in v13/v14
  5. Future Direction: Persistence-Initiative arbeitet an decoupled Architecture – Timeline: v15+

9.2 Handlungsempfehlungen

Batch Processing = Pflicht

Für alle Bulk-Operations ab 100+ Records Batch-Processing implementieren. Diese Strategie ist version-agnostisch und liefert konsistent 90+ % Performance-Improvement.

Version-Migration nicht für Performance

Migrieren Sie zu v13/v14 für Features, Security, LTS – nicht primär für DataHandler-Performance. Die Gains sind messbar, aber nicht business-critical.

Code einmal schreiben

Optimierungs-Code aus v12 läuft unmodified in v13/v14. Investieren Sie in robusten, version-agnostischen Bulk-Import-Code.

Persistence-Initiative monitoren

Verfolgen Sie die Persistence-Initiative. Sobald neue APIs verfügbar sind, evaluieren Sie Migration für Custom High-Performance-Pipelines.

Database-Foundation

Proper Indexing aller relevanten Columns ist Foundation. Ohne korrekte Indexes verpuffen alle PHP-Level-Optimierungen.

Transaction Atomicity

Nutzen Sie Doctrine Transactions für Batch-Operations: beginTransaction(), commit(), rollback(). Data-Integrity bei Performance-Optimierung.


X. Appendix: DDEV-Setup für Multi-Version-Benchmarks

10.1 Master-Benchmark-Script

Vollständig automatisiertes Setup und Benchmark-Execution über alle drei TYPO3-Versionen:

#!/bin/bash
set -e

VERSIONS=("v12" "v13" "v14")
RESULTS_DIR="./benchmark-results"

mkdir -p "$RESULTS_DIR"

echo "=========================================="
echo "TYPO3 DataHandler Multi-Version Benchmark"
echo "=========================================="

for VERSION in "${VERSIONS[@]}"; do
    echo ""
    echo "Setting up TYPO3 $VERSION..."
    
    PROJECT_DIR="typo3-benchmark-$VERSION"
    
    # Cleanup previous runs
    if [ -d "$PROJECT_DIR" ]; then
        cd "$PROJECT_DIR"
        ddev delete -O -y
        cd ..
        rm -rf "$PROJECT_DIR"
    fi
    
    # Create project
    mkdir "$PROJECT_DIR"
    cd "$PROJECT_DIR"
    
    # DDEV config
    if [ "$VERSION" = "v14" ]; then
        # Clone v14 from main branch
        git clone https://github.com/typo3/typo3.git .
        ddev config --project-type=typo3 --php-version=8.3
    elif [ "$VERSION" = "v13" ]; then
        ddev config --project-type=typo3 --php-version=8.2
        ddev composer create "typo3/cms-base-distribution:^13.0"
    else
        ddev config --project-type=typo3 --php-version=8.1
        ddev composer create "typo3/cms-base-distribution:^12.0"
    fi
    
    # Start DDEV
    ddev start
    
    # Install TYPO3
    ddev exec touch public/FIRST_INSTALL
    ddev typo3 setup --server-type=other \
        --admin-username=admin \
        --admin-user-password=password \
        --admin-email=admin@example.com \
        --no-interaction
    
    # Install faker
    ddev composer require fakerphp/faker
    
    # Copy benchmark commands
    cp ../benchmark-commands/* Classes/Command/
    
    echo "Generating 10,000 test records..."
    ddev exec vendor/bin/typo3 data:generate 10000
    
    echo "Running baseline benchmark..."
    BASELINE_OUTPUT=$(ddev exec vendor/bin/typo3 data:import)
    echo "$BASELINE_OUTPUT" > "../$RESULTS_DIR/${VERSION}-baseline.txt"
    
    echo "Running optimized benchmark..."
    OPTIMIZED_OUTPUT=$(ddev exec vendor/bin/typo3 data:import \
        --batch-size=500 \
        --disable-logging \
        --bypass-permissions \
        --disable-versioning)
    echo "$OPTIMIZED_OUTPUT" > "../$RESULTS_DIR/${VERSION}-optimized.txt"
    
    cd ..
    
    echo "✓ Completed TYPO3 $VERSION benchmarks"
done

echo ""
echo "=========================================="
echo "Benchmarks completed!"
echo "Results: $RESULTS_DIR/"
echo "=========================================="

Automation-Advantage

Das Script ermöglicht reproduzierbare Benchmarks auf jedem DDEV-fähigen System. Execution Time: ~30 Minuten für alle drei Versionen.

10.2 DDEV-Konfiguration pro Version

v12 Configuration:

name: typo3-benchmark-v12
type: typo3
php_version: "8.1"
docroot: public
database:
  type: mariadb
  version: "10.11"

v13 Configuration:

name: typo3-benchmark-v13
type: typo3
php_version: "8.2"
docroot: public
database:
  type: mariadb
  version: "10.11"

v14 Configuration:

name: typo3-benchmark-v14
type: typo3
php_version: "8.3"
docroot: public
database:
  type: mariadb
  version: "11.0"

Referenzen

[1] TYPO3 Documentation. (n.d.). DataHandler Introduction. Retrieved from https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DataHandler/Introduction/Index.html

[2] TYPO3 Documentation. (n.d.). DataHandler basics. Retrieved from https://docs.typo3.org/permalink/t3coreapi:datahandler-basics

[3] TYPO3.org. (n.d.). Datahandler & Persistence Initiative. Retrieved from https://typo3.org/community/teams/typo3-development/initiatives/persistence

[4] DDEV Documentation. (n.d.). DDEV Configuration. Retrieved from https://docs.ddev.com/en/stable/users/configuration/config/

[5] TYPO3 Documentation. (n.d.). Installing and using DDEV. Retrieved from https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/Installation/UsingDdev.html

[6] GitHub. (n.d.). wazum/transactional-data-handler. Retrieved from https://github.com/wazum/transactional-data-handler

[7] TYPO3 API Documentation. (n.d.). Class TYPO3\CMS\Core\DataHandling\DataHandler (v13.4). Retrieved from https://api.typo3.org/13.4/classes/TYPO3-CMS-Core-DataHandling-DataHandler.html

[8] derhansen.de. (2023). The pitfalls of reusing TYPO3 QueryBuilder. Retrieved from https://www.derhansen.de/2023/10/the-pitfalls-of-reusing-typo3-querybuilder-analyzing-a-performance-bottleneck.html


Für Fragen zur Implementation: office@webconsulting.at

Lassen Sie uns über Ihr Projekt sprechen

Standorte

  • Mattersburg
    Johann Nepomuk Bergerstraße 7/2/14
    7210 Mattersburg, Austria
  • Wien
    Ungargasse 64-66/3/404
    1030 Wien, Austria

Dieser Inhalt wurde teilweise mithilfe von KI erstellt.