Slide 1

Slide 1 text

A modern app server for PHP https://frankenphp.dev

Slide 2

Slide 2 text

➔ PHP API Platform creator, Symfony maintainer ➔ GO Go core contributor, Mercure.rocks and Vulcain.rocks creator ➔ C PHP core contributor Kévin Dunglas: Polyglot Dev @dunglas

Slide 3

Slide 3 text

02 03 04 01 FrankenPHP?! What’s next? Internals Features

Slide 4

Slide 4 text

FrankenPHP A modern app server for PHP ➔ Built for containers ➔ Worker mode ➔ 103 Early Hints support ➔ Real-time support (Mercure module) ➔ Compatible with all existing PHP apps: ◆ progressive enhancement

Slide 5

Slide 5 text

PHP and Containers

Slide 6

Slide 6 text

Containers: Which SAPI? Server Application Programming Interface: interface between the PHP interpreter and web servers ➔ Apache module ➔ FPM (FastCGI Process Manager) ➔ CGI (Common Gateway Interface) ➔ NGINX Unit (not the NGINX you’re used to) ➔ …

Slide 7

Slide 7 text

➔ Simple ➔ Web server + PHP = 1 service ➔ Default solution for containers DRAWBACKS: ➔ Works only with Apache ➔ Less performant than FPM Apache Module

Slide 8

Slide 8 text

FPM ➔ Most popular SAPI ➔ Supported by most web servers: Caddy, Symfony CLI, NGINX, Apache… DRAWBACKS: ➔ External service ➔ Require a UNIX or a TCP socket ➔ Hard to containerize

Slide 9

Slide 9 text

© sergioska FPM and containers

Slide 10

Slide 10 text

Can We Do Better?!

Slide 11

Slide 11 text

➔ Secure and fast ➔ Easy to configure ➔ Cloud native: API, hot config reloading… ➔ Automatic HTTPS ➔ HTTP/2, HTTP/3, Early Hints… ➔ Extensible with modules: Mercure, Vulcain, OAuth, OIDC… ➔ Prod ready ➔ Written in Go 😻 Caddy: The New Kid on the Block

Slide 12

Slide 12 text

➔ Perfect for containers ◆ Just 1 service ◆ No external dependencies ➔ Built on top of Caddy ◆ All Caddy features and modules ◆ Benefits from Go features ◆ Extensible: in Go, in C, in PHP ➔ Prod, CI and dev FrankenPHP: Modern PHP App Server

Slide 13

Slide 13 text

➔ Standalone Go library ➔ Embed PHP in your Go programs ➔ New SAPI for Go net/http ◆ Caddy, Symfony CLI, Traefik, K8S… ◆ Your custom Go app ➔ Caddy module using the library ➔ Unique features The ❤ of FrankenPHP: A New SAPI For Go

Slide 14

Slide 14 text

02 03 04 01 FrankenPHP?! Features What’s next? Internals

Slide 15

Slide 15 text

➔ Compatible with existing PHP apps! ➔ 1 service, 1 container image 😍 ➔ Also works without Docker ➔ Entirely configurable ◆ Caddyfile ◆ php.ini ➔ Free software (as in free speech ✊, and free beer 🍺) FrankenPHP: At a Glance

Slide 16

Slide 16 text

Getting Started

Slide 17

Slide 17 text

Getting Started

Slide 18

Slide 18 text

FrankenPHP Superpower: The Worker Mode ➔ Boot your application once ➔ Keep it in memory ➔ Process incoming requests without having to boot your app again ➔ Relies on goroutines and channels ➔ Compatible with Symfony Runtime and Laravel Octane (soon) ➔ Somewhat similar to RoadRunner ➔ Unlike RR, uses plain old superglobals

Slide 19

Slide 19 text

Worker Script

Slide 20

Slide 20 text

Starting the Worker Mode By default, one worker per CPU is started.

Slide 21

Slide 21 text

Symfony App in Worker Mode

Slide 22

Slide 22 text

FrankenPHP: Worker Benchmark 🧪 ➔ Setup: ◆ Hello World Symfony app (prod mode) ◆ Caddy Web Server (HTTP/2) ◆ 3000 requests, 100 connected users ◆ Benchmark tool: K6 ➔ Average request duration: ◆ FPM: 9.45ms ◆ FrankenPHP (no worker): 12.72ms ◆ FrankenPHP (worker): 2.53ms

Slide 23

Slide 23 text

103 Early Hints

Slide 24

Slide 24 text

Typical Web Page © Google

Slide 25

Slide 25 text

103 Early Hints © Google

Slide 26

Slide 26 text

Early Hints: Not Possible With PHP

Slide 27

Slide 27 text

Early Hints: Possible With Go

Slide 28

Slide 28 text

Early Hints: Supported by FrankenPHP ⚡

Slide 29

Slide 29 text

03 01 Features Internals 02 04 FrankenPHP?! What’s next?

Slide 30

Slide 30 text

➔ PHP scripts are interpreted ➔ The PHP interpreter is written in C ➔ php-src uses Zend Engine ◆ compiler (with Just In Time) ◆ executor (Virtual Machine) ➔ SAPIs ◆ Pass input from the web server to the PHP engine ◆ Pass output from the the PHP engine to the web server PHP Internals: the Basics

Slide 31

Slide 31 text

The embed SAPI

Slide 32

Slide 32 text

PHP as a C Library ➔ PHP can be used by C programs as a library ◆ It’s how the Apache module works ➔ The embed SAPI eases the process for simple cases ➔ The library can be linked ◆ dynamically (.so) ◆ statically

Slide 33

Slide 33 text

➔ Go is a compiled language ➔ Go programs can call C code ➔ Go and C files can be compiled in a single program ➔ The resulting binary can be static! ➔ The native package to call C code is called cgo ➔ Using cgo we can embed PHP in Caddy, Symfony CLI and other Go programs! C? Go? Cgo!

Slide 34

Slide 34 text

C function to execute a PHP script

Slide 35

Slide 35 text

Call the function from Go!

Slide 36

Slide 36 text

Tadam!

Slide 37

Slide 37 text

➔ Go is especially convenient to build servers and network apps ➔ net/http: native package to create HTTP clients and servers ➔ Production-grade: optimized and secure ➔ Native HTTP/2 (HTTP/3 with a 3rd party lib) ➔ Used by Caddy, Symfony CLI, Kubernetes, Traefik, Google, Cloudflare… net/http

Slide 38

Slide 38 text

A Web Server in 5 LOC

Slide 39

Slide 39 text

A PHP SAPI for Go net/http ➔ SAPI: bridge between a server and the PHP engine ➔ Use cgo to call PHP with data coming from Go’s HTTP messages ➔ Extract data from Go’s http.Request, pass it to PHP ➔ Write data generated by PHP using Go’s http.ResponseWriter

Slide 40

Slide 40 text

The Idea

Slide 41

Slide 41 text

FrankenPHP SAPI module struct

Slide 42

Slide 42 text

Delegating to Go

Slide 43

Slide 43 text

We Have a Thread Safety Problem!

Slide 44

Slide 44 text

➔ net/http is based on the flagship feature of Go: goroutines ➔ Goroutines are lightweight threads ➔ Goroutines are executed concurrently ➔ Goroutines can run in parallel on different CPUs ➔ Go provides user-friendly synchronization mechanisms (channels) Goroutines

Slide 45

Slide 45 text

PHP Process-based Model (non-ZTS) 1 PHP process handles only 1 request concurrently. To handle requests simultaneously, start new OS processes. Model of FPM and CLI.

Slide 46

Slide 46 text

Thread-based model (ZTS) With ZTS (Zend Thread Safety), the PHP interpreter is isolated into a thread.

Slide 47

Slide 47 text

Recompile PHP with --enable-zts and…

Slide 48

Slide 48 text

➔ Goroutines are lightweight threads: a mix of real parallelism (system threads) and asynchronous I/O ➔ Several goroutines share the same OS thread ➔ Goroutines are lighter and faster than OS threads… ➔ …but ZTS isn’t enough to ensure PHP memory safety 😱 PHP must run in its own threads! Goroutines Aren’t OS Threads

Slide 49

Slide 49 text

Taming the Beast 🐘 (php-src)

Slide 50

Slide 50 text

🤩

Slide 51

Slide 51 text

No OPcache? 🤔

Slide 52

Slide 52 text

SAPIs supported By OPCache…

Slide 53

Slide 53 text

Patch coming!

Slide 54

Slide 54 text

03 01 What’s next? 02 04 Features FrankenPHP?! Internals

Slide 55

Slide 55 text

Available right now: frankenphp.dev github.com/dunglas/frankenphp

Slide 56

Slide 56 text

➔ 🧪 Still highly experimental! ➔ Fix the remaining segfaults issues ➔ Test, test and test again ➔ Add support to Laravel Octane ➔ Use it in Symfony CLI ➔ Add Windows support ➔ Contributions welcome! What’s next?!

Slide 57

Slide 57 text

Try it, give it a star on GitHub. Thanks! frankenphp.dev @dunglas