[{"data":1,"prerenderedAt":216},["ShallowReactive",2],{"navigation":3,"/docs/benchmarks/reading-your-results":92,"/docs/benchmarks/reading-your-results-surround":211},[4],{"title":5,"path":6,"stem":7,"children":8,"page":39},"Docs","/docs","docs",[9,25,40,60,76,84],{"title":10,"path":11,"stem":12,"children":13,"icon":24},"Getting Started","/docs/getting-started","docs/1.getting-started/1.index",[14,16,20],{"title":15,"path":11,"stem":12},"Introduction",{"title":17,"path":18,"stem":19},"Quick start","/docs/getting-started/quick-start","docs/1.getting-started/2.quick-start",{"title":21,"path":22,"stem":23},"Running from source","/docs/getting-started/running-from-source","docs/1.getting-started/3.running-from-source","i-lucide-rocket",{"title":26,"icon":27,"path":28,"stem":29,"children":30,"page":39},"Configuration","i-lucide-settings-2","/docs/configuration","docs/2.configuration",[31,35],{"title":32,"path":33,"stem":34},"Adding a real database","/docs/configuration/adding-databases","docs/2.configuration/1.adding-databases",{"title":36,"path":37,"stem":38},"Customizing the image","/docs/configuration/customizing-the-image","docs/2.configuration/2.customizing-the-image",false,{"title":41,"path":42,"stem":43,"children":44,"icon":59},"Image variations","/docs/image-variations","docs/3.image-variations/1.index",[45,47,51,55],{"title":46,"path":42,"stem":43},"Choosing a variation",{"title":48,"path":49,"stem":50},"FPM-NGINX","/docs/image-variations/fpm-nginx","docs/3.image-variations/2.fpm-nginx",{"title":52,"path":53,"stem":54},"FrankenPHP","/docs/image-variations/frankenphp","docs/3.image-variations/3.frankenphp",{"title":56,"path":57,"stem":58},"FPM-Apache","/docs/image-variations/fpm-apache","docs/3.image-variations/4.fpm-apache","i-lucide-layers",{"title":61,"path":62,"stem":63,"children":64,"icon":75},"Benchmarks & Methodology","/docs/benchmarks","docs/4.benchmarks/1.index",[65,67,71],{"title":66,"path":62,"stem":63},"Methodology",{"title":68,"path":69,"stem":70},"Reading your results","/docs/benchmarks/reading-your-results","docs/4.benchmarks/2.reading-your-results",{"title":72,"path":73,"stem":74},"Testing from your own machine","/docs/benchmarks/testing-from-your-own-machine","docs/4.benchmarks/3.testing-from-your-own-machine","i-lucide-flask-conical",{"title":77,"path":78,"stem":79,"children":80,"icon":83},"Community Results","/docs/community-results","docs/5.community-results/1.index",[81],{"title":82,"path":78,"stem":79},"Submitting your results","i-lucide-users",{"title":85,"path":86,"stem":87,"children":88,"icon":91},"FAQ","/docs/faq","docs/6.faq/1.index",[89],{"title":90,"path":86,"stem":87},"Frequently asked questions","i-lucide-circle-help",{"id":93,"title":68,"body":94,"description":203,"extension":204,"links":205,"meta":206,"navigation":207,"path":69,"redirect":205,"seo":208,"sitemap":209,"stem":70,"__hash__":210},"docs/docs/4.benchmarks/2.reading-your-results.md",{"type":95,"value":96,"toc":191},"minimark",[97,101,104,109,112,117,120,132,136,139,142,146,149,162,166,169,175,179,182,185],[98,99,100],"p",{},"BenchKit is at its most accurate when you compare two runs from the same machine. Run it, change one thing, run it again, and the difference between the two is what that change was worth. Everything else on the machine stayed the same. Nothing else can explain the gap.",[98,102,103],{},"Comparing your machine against somebody else's in the gallery works too, and it is the reason the gallery exists. Just hold the comparison more loosely, because their host, their tuning, and their neighbours on that hardware are all different from yours.",[105,106,108],"h2",{"id":107},"known-limits","Known limits",[98,110,111],{},"Every benchmark tool has limits. The ones below apply to BenchKit, and each comes with what to do about it.",[113,114,116],"h3",{"id":115},"the-load-generator-runs-on-the-same-machine","The load generator runs on the same machine",[98,118,119],{},"By default oha runs on the machine it is testing, alongside the application and the database. All three compete for the same CPU. Keeping everything on one box is what makes an A and B comparison clean, because the request path is identical between your two runs. It also means the absolute requests per second is lower than the machine could serve if the traffic came from somewhere else.",[98,121,122,123,127,128,131],{},"When you want the absolute number, open ",[124,125,126],"strong",{},"Test from your own machine"," in the app. It gives you the same oha commands to copy, pointed at your server. Drive the load from your own laptop or from another server, and the generator comes off the box entirely. See ",[129,130,72],"a",{"href":73},".",[113,133,135],{"id":134},"php-fpms-pool-size-caps-concurrency","PHP-FPM's pool size caps concurrency",[98,137,138],{},"Under PHP-FPM a request holds a worker for its whole duration, including any time it spends waiting. The pool size therefore sets a hard ceiling on concurrency that no amount of CPU can raise, and the ceiling is most obvious on the route that waits.",[98,140,141],{},"The shipped pool size is fixed rather than sized to your hardware. A large machine can end up measuring a fraction of itself. BenchKit works out how many of your cores could have been busy and tells you on the result when workers were the limit, along with the environment variable to raise. Raise it and run again before you read anything into an FPM against worker mode comparison.",[113,143,145],{"id":144},"the-built-in-test-measures-throughput-not-tail-latency","The built-in test measures throughput, not tail latency",[98,147,148],{},"The load test holds a fixed number of connections open and measures how much the server can get through. When a fixed-connection client meets a server that slows down, the client waits rather than sending more. The reported p95 and p99 then come out better than reality. Gil Tene named this coordinated omission.",[98,150,151,152,154,155,159,160,131],{},"BenchKit labels its own tail percentiles as indicative for that reason. If you care about latency targets, use the corrected command in ",[124,153,126],{},", which drives a constant request rate and passes ",[156,157,158],"code",{},"--latency-correction"," to oha. Find your maximum throughput with a normal run first, then measure latency at a rate below it. See ",[129,161,72],{"href":73},[113,163,165],{"id":164},"sqlite-is-the-default-database","SQLite is the default database",[98,167,168],{},"SQLite runs inside the PHP process. It has no connection cost and none of the indexing and contention behavior of a database server, and it is there to let BenchKit run with no setup at all.",[98,170,171,172,174],{},"If your application talks to MySQL or Postgres, point BenchKit at one. See ",[129,173,32],{"href":33},". Every result records which engine produced it.",[105,176,178],{"id":177},"comparing-two-runs-fairly","Comparing two runs fairly",[98,180,181],{},"Change one thing at a time, and keep everything else identical. When you compare image variations, tune both sides before you decide, because a default FPM pool against a default FrankenPHP tells you about the defaults rather than about the two servers.",[98,183,184],{},"One connection count is one point on a curve. A server that wins at low concurrency can lose at high concurrency. Run the comparison at more than one connection count before you decide.",[186,187,188],"note",{},[98,189,190],{},"Whatever BenchKit tells you, the workload it runs is not your application. Use it to find which changes help, then confirm the promising ones against your own code.",{"title":192,"searchDepth":193,"depth":193,"links":194},"",2,[195,202],{"id":107,"depth":193,"text":108,"children":196},[197,199,200,201],{"id":115,"depth":198,"text":116},3,{"id":134,"depth":198,"text":135},{"id":144,"depth":198,"text":145},{"id":164,"depth":198,"text":165},{"id":177,"depth":193,"text":178},"What a BenchKit number tells you, and the known limits that apply to it.","md",null,{},true,{"title":68,"description":203},{"loc":69},"jKktTuCCTpm6foUxvFUpiG5nAha3Rw6_GC67uaUH1QE",[212,214],{"title":66,"path":62,"stem":63,"description":213,"children":-1},"What each stage measures and how a run is put together.",{"title":72,"path":73,"stem":74,"description":215,"children":-1},"Drive the load test from a different machine with oha, and measure tail latency honestly.",1786740096072]