The PHP Bench

PHP ORMs 2026

Comprehensive ORM benchmarks for every scenario.

Imports
1
Inbox Rows
1
Runs
312
Metrics
16,224
Matrices
52
Scenarios
6
Fastest Stack
Atlas
Storage
sqlite-memory
Speed
0.011893s

Fastest Combinations

Atlas
sqlite-memory · 2.0.1
0.011893s
PHPFUI
sqlite-memory · 3.0.3
0.022028s
Cycle
sqlite-memory · 2.16.0
0.023986s
PHPFUIBatch
sqlite-memory · 3.0.3
0.024710s
Propel2
sqlite-memory · 6cb272b6
0.045488s
ActiveRecord
sqlite-memory · 2.0.6
0.046491s
RedBean
sqlite-memory · 5.7.5
0.054854s
DivergenceV3
sqlite-memory · 3.2.0
0.058695s
Atlas
mariadb · 2.0.1
0.059061s
Cycle
postgresql · 2.16.0
0.060871s
Yii
sqlite-memory · 2.0.54
0.061358s
PHPFUIBatch
mariadb · 3.0.3
0.072125s
Cycle
mariadb · 2.16.0
0.072922s
PHPFUI
mariadb · 3.0.3
0.076672s
Atlas
sqlite-file · 2.0.1
0.085864s
Atlas
postgresql · 2.0.1
0.087134s
Propel2
mariadb · 6cb272b6
0.092292s
DivergenceV2
mariadb · 2.1.4
0.099256s

Inbox

ID Status Runner Runtime File
#1 processed runner-20260329222123 39.501s
avg 0.126606s
results-20260329203643-74505162-default-20260329-203643.csv

How Scenario Families Shift Rankings

Family Pressure Why It Changes Speed Avg Runtime
simple baseline row shape Shows framework overhead with very little field-mapping noise, so identity-map, query builder, and per-record object cost dominate. 0.099689s
canary mixed nullable and cast-heavy fields Wide records amplify hydration, casting, dirty-checking, and serialization overhead. Frameworks with expensive attribute normalization usually spread out here. 0.154049s
int_fixed narrow scalar writes A near-floor for typed persistence. If an ORM is still slow here, the cost is usually framework machinery rather than payload complexity. 0.123969s
float_fixed numeric conversion and precision paths Decimal and floating-point mapping can trigger extra normalization work, especially on update verification and dirty-state comparison. 0.141195s
string_fixed predictable text hydration Fixed-length text stresses text field assignment without the variability of large blobs, so column-count and hydration strategy matter more than payload churn. 0.118621s
string_variable application-style text records This is the closest to a real CRUD app payload. Variable strings and notes fields widen the gap between lightweight row mappers and heavier active-record layers. 0.122112s
Operation Shape Why Models Move
Warmup vs hot runs Run 1 is a warmup pass. Hot-path rankings exclude it so adapter boot, metadata discovery, and first-query setup do not drown out steady-state behavior.
Insert and indexed schemas Indexed variants make inserts more expensive because each row write updates secondary indexes. ORMs that already have heavy unit-of-work overhead get exposed harder there.
Read all vs read probes Read All rewards efficient bulk hydration. Random and tail probes reveal per-query setup cost, identity lookup behavior, and how much work happens for tiny result sets.
Update with verification Updates are followed by read-back verification. That means slow dirty-checking, full-row writes, cast normalization, and post-update reads all feed into the total.
Delete phase Delete cost is not just delete. The harness verifies the row is actually gone, so frameworks with slow teardown or follow-up lookup behavior pay twice.
Total runtime Total runtime is a whole-machine workload number: init, insert, every read shape, every update shape, verification passes, and delete.

Storage Engine Curve

sqlite-memory
0.069814s
mariadb
0.127033s
sqlite-file
0.142422s
postgresql
0.167155s

Scenario Families

simple
0.099689s
string_fixed
0.118621s
string_variable
0.122112s
int_fixed
0.123969s
float_fixed
0.141195s
canary
0.154049s

Imports

Run Host Status Rows Runtime Started
20260329203643-74505162 eimu
8.5.3
complete 16,224 39.501s
avg 0.126606s