Slide 1

Slide 1 text

2025: Performance Milestone for the Symfony Ecosystem

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

20 years of Symfony ✔ From Symfony 1 to Symfony 4+ ✔ Innovation and Backward compatibility ✔ Flex ✔ Adaptable and performant

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Dependency Injection use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; $container = new ContainerBuilder(); // ... register services and parameters ... $container->compile(); $dumper = new PhpDumper($container); file_put_contents('Container.php', $dumper->dump());

Slide 7

Slide 7 text

PHP dumping optimization Routing Dependency Injection Translation Twig Config Expression Language Cache

Slide 8

Slide 8 text

✔ streaming JSON interface ✔ Achieves minimal memory usage for large data volumes ✔ 10x faster serialization and 50% less memory usage JsonStreamer Component symfony.com/blog/new-in-symfony-7-3-jsonstreamer-component

Slide 9

Slide 9 text

Requests per Second

Slide 10

Slide 10 text

Time to First Byte

Slide 11

Slide 11 text

JsonStreamer vs Serializer

Slide 12

Slide 12 text

JsonStreamer Caveats ✔ Error handling during streaming ✔ Only public properties ✔ Harder to customize than normalizers

Slide 13

Slide 13 text

JSON-LD { "@context": "/contexts/Book", "@id": "/books/25", "@type": "https://schema.org/Book", "title": "1984", "condition": "https://schema.org/UsedCondition", "author": "/authors/20" } https:/ /edge-side-apis.rocks

Slide 14

Slide 14 text

use Symfony\Component\JsonStreamer\Mapping\PropertyMetadata; use Symfony\Component\JsonStreamer\Mapping\PropertyMetadataLoaderInterface; use Symfony\Component\TypeInfo\Type; final class WritePropertyMetadataLoader implements PropertyMetadataLoaderInterface { public function load(string $className, array $options = [], array $context = []): array { $properties = $this->loader->load($className, $options, $context); $properties['@id'] = PropertyMetadata::createSynthetic( Type::string(), ['api_platform.jsonld.json_streamer.write.value_transformer.iri'] ); // ... return $properties; } }

Slide 15

Slide 15 text

use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\IriConverterInterface; use Symfony\Component\JsonStreamer\ValueTransformer\ValueTransformerInterface; final class IriValueTransformer implements ValueTransformerInterface { public function __construct(private readonly IriConverterInterface $iriConverter) {} public function transform(mixed $value, array $options = []): mixed { return $this->iriConverter->getIriFromResource( $options['_current_object'], UrlGeneratorInterface::ABS_PATH, $options['operation'] instanceof CollectionOperationInterface ? null : $options['operation'], ); } }

Slide 16

Slide 16 text

API Platform #[ApiResource(jsonStream: true)]

Slide 17

Slide 17 text

✓ Mapping of nested classes with promoted read-only properties ✓ Map to embedded object with property access ✓ Bypass lazy ghost with class transform ✓ Lazy loading ✓ Cache attributes in memory (soyuka) ObjectMapper (7.4/8.0)

Slide 18

Slide 18 text

xDebug Profile php ./vendor/bin/phpbench xdebug:profile --outdir profile

Slide 19

Slide 19 text

Future optimizations ? ✔ Object Mapper (symfony/pull/61515) 50% perf improvement ✔ Serializer (symfony/pull/52905) 87% perf improvement (by @Nyholm Tobias Nyholm) Help reviewing!

Slide 20

Slide 20 text

✔ API Platform release manager ✔ Developer, biker, builder ✔ Father ✔ Open source advocate ✔ CTO at Les-Tilleuls.coop Antoine Bluchet aka soyuka https:/ /github.com/soyuka

Slide 21

Slide 21 text

Web and cloud experts https:/ /github.com/sponsors/api-platform

Slide 22

Slide 22 text

10 years of API Platform ✔ API Platform 4.2 ✔ JsonStreamer component ✔ ObjectMapper component

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Sylius ✔ PHP ✔ It’s a Symfony-based framework ✔ E-commerce ✔ Compatible with API Platform

Slide 30

Slide 30 text

30 years of PHP ✔ PHP 8 revolution ✔ PHP Foundation (2021) ✔ JIT ✔ Lazy proxies / ghost JetBrains PHPverse 2025

Slide 31

Slide 31 text

30 years of PHP!

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

FrankenPHP with Docker FROM dunglas/frankenphp:php8.5 # add additional extensions here: RUN install-php-extensions \ pdo_mysql \ gd \ intl \ exif \ zip \ opcache ENV FRANKENPHP_CONFIG="worker ./public/index.php" RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini COPY php-tweaks.ini /usr/local/etc/php/conf.d/php-tweaks.ini COPY . /app Symfony 7.4 detects the worker mode see https:/ /github.com/symfony/symfony/pull/60503

Slide 34

Slide 34 text

Tips ✓ Cloud ready: environment variables for every configuration ✓ Log to stderr is a good practice with containers ✓ Single container really helps with pragmatic configuration ✓ Watch mode to restart the worker in dev mode symfony.com/doc/current/performance.html

Slide 35

Slide 35 text

NGINX vs FrankenPHP Scaleway DEV1-S (2 vCPUs, 2 GB RAM) Database Server: 2 vCPUs, 2 GB RAM, MySQL Benchmark Tool: wrk (on a separate DEV1-S instance) Nginx + PHP-FPM: pm.max_children = 15 FrankenPHP (Worker Mode): worker.num = 36 FrankenPHP (Thread Mode): num_threads = 36 (Worker vs. Thread) Performance Benchmark on a Sylius Application

Slide 36

Slide 36 text

Requests per Second https:/ /soyuka.github.io/sylius-benchmarks/

Slide 37

Slide 37 text

Average latency (ms) https:/ /soyuka.github.io/sylius-benchmarks/

Slide 38

Slide 38 text

Conclusion ✔ Use worker mode ✔ Find worker { num } sweet spot ✔ Must read: github.com/php/frankenphp/discussio ns/1981

Slide 39

Slide 39 text

PHP Extensions in Go ✔ Go ecosystem is awesome ✔ frankenphp extension-init Scaffolder ✔ Declare your php functions in go comments frankenphp.dev/docs/extensions/

Slide 40

Slide 40 text

QRCode ✔ Faster ✔ Less memory usage github.com/soyuka/php-go-qrcode

Slide 41

Slide 41 text

Thanks! github.com/soyuka x.com/s0yuka bsky.app/soyuka.me phpc.social/@soyuka