SkillAgentSearch skills...

FrankenVSRoadRunner

Benchmark application comparing FrankenPHP and RoadRunner on the Symfony 8 & PHP 8.4 stack. Includes multiple scenarios testing CPU, I/O, memory, and serialization performance in containerized environments.

Install / Use

/learn @mattleads/FrankenVSRoadRunner
About this skill

Quality Score

0/100

Supported Platforms

Zed

README

Symfony 8 Benchmark: FrankenPHP vs. RoadRunner

This project is a comprehensive benchmark application built with Symfony 8, designed to compare the performance, memory management, and stability of two popular PHP application servers: FrankenPHP and RoadRunner.

It includes a suite of API endpoints that simulate various real-world workloads, from simple health checks to CPU-intensive image processing and memory-heavy serialization tasks.

Key Features

  • Multiple Benchmark Scenarios: Test different aspects of server performance.
  • Dockerized Environments: Easy-to-use, isolated setups for both FrankenPHP and RoadRunner.
  • Symfony 8 & PHP 8.4: Built with modern PHP and the latest Symfony framework.
  • Best Practices: Demonstrates correct state management (ResetInterface) for long-running worker environments.
  • Realistic Workloads: Includes tests for CPU, I/O, memory pressure, and stateful services.

Technologies Used

  • PHP 8.4
  • Symfony 8.0
  • Doctrine ORM
  • FrankenPHP (via Docker)
  • RoadRunner (via Docker)
  • Docker & Docker Compose

Prerequisites

  • Docker
  • Docker Compose

Installation

  1. Clone the repository:

    git clone https://github.com/mattleads/FrankenVSRoadRunner.git
    cd FrankenVSRoadRunner
    
  2. Install PHP dependencies: This is necessary for your IDE to recognize classes and for local development. The Docker images will handle their own vendor installations.

    composer install
    

Database Setup

The project is pre-configured to use a local SQLite database, which will be created inside the var/ directory. Before running the benchmarks, you need to create the database schema and load the sample data.

  1. Create the Database Schema: Run the following commands to generate and apply the necessary database migrations for the Product, Order, and OrderItem entities.

    php bin/console make:migration
    php bin/console doctrine:migrations:migrate
    

    (You may be asked to confirm the execution.)

  2. Load Fixture Data: This command will purge the database and then seed it with a large set of sample products and complex orders for the "Heavy Framework" benchmark.

    php bin/console doctrine:fixtures:load
    

    (You will be asked to confirm that you want to purge the database.)

Running the Application

You can run the application using either FrankenPHP or RoadRunner. The Docker Compose setups are configured to run on the same port (8080), so only run one at a time or you can change it.

Option 1: Running with FrankenPHP

This will build a custom Docker image with the required PHP extensions and start the FrankenPHP server.

docker-compose -f compose.frankenphp.yaml up -d --build
  • URL: http://localhost:8080

Option 2: Running with RoadRunner

This will build a multi-stage, optimized Docker image and start the RoadRunner server.

docker-compose -f compose.roadrunner.yaml up -d --build
  • URL: http://localhost:8080

Usage Guide: Benchmark Endpoints

All endpoints are available under the /api/v1 prefix.


1. Ping / Health Check

  • Description: A simple "hello world" endpoint to test basic request/response throughput and worker state.
  • Method: GET
  • Endpoint: /api/v1/ping

Example:

curl http://localhost:8080/api/v1/ping

Response:

{
  "status": "pong",
  "timestamp": 1678886400,
  "request_count_for_this_worker": 1
}

2. Basic Database Interaction

  • Description: Tests the overhead of database connections and object creation.
  • Method: POST
  • Endpoint: /api/v1/products

Example:

curl -X POST http://localhost:8080/api/v1/products 
     -H "Content-Type: application/json" 
     -d '{"name": "Benchmark Pro", "price": 1999}'

3. The "Number Cruncher" (CPU Bound)

  • Description: Measures raw execution speed by performing a heavy matrix multiplication.
  • Method: GET
  • Endpoint: /api/v1/math/matrix/{size} (e.g., /api/v1/math/matrix/100)

Example:

curl http://localhost:8080/api/v1/math/matrix/100

4. The "Big Data Stream" (I/O & Memory Bound)

  • Description: Tests the server's ability to stream a large response without buffering it into memory. This generates and streams a 100,000-row CSV file.
  • Method: GET
  • Endpoint: /api/v1/report/stream

Example (saves the output to a file):

curl -O http://localhost:8080/api/v1/report/stream

5. The "Pixel Cruncher" (Image Processing)

  • Description: Simulates a heavy, blocking image manipulation task (resize and grayscale).
  • Method: POST
  • Endpoint: /api/v1/media/process

Example (assumes you have an image named my-photo.jpg):

# The -F flag sends a multipart/form-data request
curl -X POST -F "image=@my-photo.jpg" 
     http://localhost:8080/api/v1/media/process 
     -o processed_image.jpg

6. The "Heavy Framework" Boot Test (Serialization)

  • Description: Stresses the serializer and memory manager by fetching and serializing a collection of 50 complex, nested Doctrine entities.
  • Method: GET
  • Endpoint: /api/v1/heavy/orders

Example:

curl http://localhost:8080/api/v1/heavy/orders

7. The "Keep-Alive" & Memory Leak Stress Test

  • Description: Intentionally leaks 1MB of memory on each request to test how gracefully the server handles worker recycling (based on memory limits, TTL, or max requests).
  • Method: GET
  • Endpoint: /api/v1/leak

Example:

# Run this command multiple times to observe the "memory" value increasing
curl http://localhost:8080/api/v1/leak
View on GitHub
GitHub Stars6
CategoryDevelopment
Updated1mo ago
Forks1

Languages

PHP

Security Score

70/100

Audited on Mar 8, 2026

No findings