[{"data":1,"prerenderedAt":1548},["ShallowReactive",2],{"navigation":3,"/docs/configuration/adding-databases":96,"/docs/configuration/adding-databases-surround":1543},[4],{"title":5,"path":6,"stem":7,"children":8,"page":59},"Docs","/docs","docs",[9,25,41,60,80,88],{"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,"path":27,"stem":28,"children":29,"icon":40},"Benchmarks & Methodology","/docs/benchmarks","docs/2.benchmarks/1.index",[30,32,36],{"title":31,"path":27,"stem":28},"Methodology",{"title":33,"path":34,"stem":35},"Reading your results","/docs/benchmarks/reading-your-results","docs/2.benchmarks/2.reading-your-results",{"title":37,"path":38,"stem":39},"Testing from another machine","/docs/benchmarks/testing-from-another-machine","docs/2.benchmarks/3.testing-from-another-machine","i-lucide-flask-conical",{"title":42,"icon":43,"path":44,"stem":45,"children":46,"page":59},"Configuration","i-lucide-settings-2","/docs/configuration","docs/3.configuration",[47,51,55],{"title":48,"path":49,"stem":50},"Adding a real database","/docs/configuration/adding-databases","docs/3.configuration/1.adding-databases",{"title":52,"path":53,"stem":54},"Customizing the image","/docs/configuration/customizing-the-image","docs/3.configuration/2.customizing-the-image",{"title":56,"path":57,"stem":58},"Common tuning strategies","/docs/configuration/common-tuning-strategies","docs/3.configuration/3.common-tuning-strategies",false,{"title":61,"path":62,"stem":63,"children":64,"icon":79},"Image variations","/docs/image-variations","docs/4.image-variations/1.index",[65,67,71,75],{"title":66,"path":62,"stem":63},"Choosing a variation",{"title":68,"path":69,"stem":70},"FPM-NGINX","/docs/image-variations/fpm-nginx","docs/4.image-variations/2.fpm-nginx",{"title":72,"path":73,"stem":74},"FrankenPHP","/docs/image-variations/frankenphp","docs/4.image-variations/3.frankenphp",{"title":76,"path":77,"stem":78},"FPM-Apache","/docs/image-variations/fpm-apache","docs/4.image-variations/4.fpm-apache","i-lucide-layers",{"title":81,"path":82,"stem":83,"children":84,"icon":87},"Community Results","/docs/community-results","docs/5.community-results/1.index",[85],{"title":86,"path":82,"stem":83},"Submitting your results","i-lucide-users",{"title":89,"path":90,"stem":91,"children":92,"icon":95},"FAQ","/docs/faq","docs/6.faq/1.index",[93],{"title":94,"path":90,"stem":91},"Frequently asked questions","i-lucide-circle-help",{"id":97,"title":48,"body":98,"description":1536,"extension":1537,"links":1538,"meta":1539,"navigation":227,"path":49,"redirect":1538,"seo":1540,"sitemap":1541,"stem":50,"__hash__":1542},"docs/docs/3.configuration/1.adding-databases.md",{"type":99,"value":100,"toc":1528},"minimark",[101,105,110,118,142,145,1390,1393,1416,1431,1438,1442,1445,1448,1451,1455,1458,1473,1477,1484,1487,1491,1502,1506,1513,1518,1524],[102,103,104],"p",{},"BenchKit uses SQLite by default so that it runs with no setup at all. SQLite runs inside the PHP process, which means it has no connection cost and none of the indexing and contention behavior you get from a database server. If you want numbers that reflect how your application talks to a real database, use Laravel's native database drivers to point BenchKit at MySQL, MariaDB, or Postgres.",[106,107,109],"h2",{"id":108},"the-two-files","The two files",[102,111,112,113,117],{},"Put both files in the same directory. Compose reads ",[114,115,116],"code",{},".env"," on its own, so you write each value once and it reaches both containers:",[119,120,121,130],"ul",{},[122,123,124,129],"li",{},[125,126,127],"strong",{},[114,128,116],{}," holds the credentials.",[122,131,132,137,138,141],{},[125,133,134],{},[114,135,136],{},"docker-compose.yml"," hands them to BenchKit as Laravel's ",[114,139,140],{},"DB_*"," variables, and to the database as the variables its own image expects.",[102,143,144],{},"Pick your engine and copy both files.",[146,147,149,655,1030],"tabs",{"sync":148},"database",[150,151,154],"tabs-item",{"icon":152,"label":153},"i-simple-icons-mysql","MySQL",[155,156,157,245],"code-tree",{"default-value":116},[158,159,164],"pre",{"className":160,"code":161,"filename":116,"language":162,"meta":163,"style":163},"language-ini shiki shiki-themes github-dark","DB_CONNECTION=mysql\nDB_HOST=mysql\nDB_PORT=3306\nDB_DATABASE=benchkit\nDB_USERNAME=benchkit\nDB_PASSWORD=benchkit_secret\n\n# Used by the database container only\nDB_ROOT_PASSWORD=root_secret\n","ini","",[114,165,166,179,187,196,205,213,222,229,236],{"__ignoreMap":163},[167,168,171,175],"span",{"class":169,"line":170},"line",1,[167,172,174],{"class":173},"snl16","DB_CONNECTION",[167,176,178],{"class":177},"s95oV","=mysql\n",[167,180,182,185],{"class":169,"line":181},2,[167,183,184],{"class":173},"DB_HOST",[167,186,178],{"class":177},[167,188,190,193],{"class":169,"line":189},3,[167,191,192],{"class":173},"DB_PORT",[167,194,195],{"class":177},"=3306\n",[167,197,199,202],{"class":169,"line":198},4,[167,200,201],{"class":173},"DB_DATABASE",[167,203,204],{"class":177},"=benchkit\n",[167,206,208,211],{"class":169,"line":207},5,[167,209,210],{"class":173},"DB_USERNAME",[167,212,204],{"class":177},[167,214,216,219],{"class":169,"line":215},6,[167,217,218],{"class":173},"DB_PASSWORD",[167,220,221],{"class":177},"=benchkit_secret\n",[167,223,225],{"class":169,"line":224},7,[167,226,228],{"emptyLinePlaceholder":227},true,"\n",[167,230,232],{"class":169,"line":231},8,[167,233,235],{"class":234},"sAwPA","# Used by the database container only\n",[167,237,239,242],{"class":169,"line":238},9,[167,240,241],{"class":173},"DB_ROOT_PASSWORD",[167,243,244],{"class":177},"=root_secret\n",[158,246,250],{"className":247,"code":248,"filename":136,"language":249,"meta":163,"style":163},"language-yaml shiki shiki-themes github-dark","services:\n  benchkit:\n    image: serversideup/benchkit-laravel:latest\n    ports:\n      - \"80:8080\"\n    environment:\n      DB_CONNECTION: ${DB_CONNECTION}\n      DB_HOST: ${DB_HOST}\n      DB_PORT: ${DB_PORT}\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n    volumes:\n      - benchkit-runs:/var/www/html/storage/app/runs\n    # See \"Why the app container needs more ports\" below\n    sysctls:\n      net.ipv4.tcp_tw_reuse: 1\n      net.ipv4.ip_local_port_range: \"1024 65535\"\n    depends_on:\n      mysql:\n        condition: service_healthy\n\n  mysql:\n    image: mysql:8.4\n    # Keep above the PHP worker count\n    command: [\"--max-connections=256\"]\n    environment:\n      MYSQL_DATABASE: ${DB_DATABASE}\n      MYSQL_USER: ${DB_USERNAME}\n      MYSQL_PASSWORD: ${DB_PASSWORD}\n      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}\n    volumes:\n      - mysql-data:/var/lib/mysql\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\"]\n      interval: 5s\n      timeout: 5s\n      retries: 10\n\nvolumes:\n  benchkit-runs:\n  mysql-data:\n","yaml",[114,251,252,261,268,280,287,295,302,312,322,332,343,354,365,373,381,387,395,407,418,426,434,445,450,458,468,474,489,496,506,516,526,537,544,552,560,594,605,615,626,631,639,647],{"__ignoreMap":163},[167,253,254,258],{"class":169,"line":170},[167,255,257],{"class":256},"s4JwU","services",[167,259,260],{"class":177},":\n",[167,262,263,266],{"class":169,"line":181},[167,264,265],{"class":256},"  benchkit",[167,267,260],{"class":177},[167,269,270,273,276],{"class":169,"line":189},[167,271,272],{"class":256},"    image",[167,274,275],{"class":177},": ",[167,277,279],{"class":278},"sU2Wk","serversideup/benchkit-laravel:latest\n",[167,281,282,285],{"class":169,"line":198},[167,283,284],{"class":256},"    ports",[167,286,260],{"class":177},[167,288,289,292],{"class":169,"line":207},[167,290,291],{"class":177},"      - ",[167,293,294],{"class":278},"\"80:8080\"\n",[167,296,297,300],{"class":169,"line":215},[167,298,299],{"class":256},"    environment",[167,301,260],{"class":177},[167,303,304,307,309],{"class":169,"line":224},[167,305,306],{"class":256},"      DB_CONNECTION",[167,308,275],{"class":177},[167,310,311],{"class":278},"${DB_CONNECTION}\n",[167,313,314,317,319],{"class":169,"line":231},[167,315,316],{"class":256},"      DB_HOST",[167,318,275],{"class":177},[167,320,321],{"class":278},"${DB_HOST}\n",[167,323,324,327,329],{"class":169,"line":238},[167,325,326],{"class":256},"      DB_PORT",[167,328,275],{"class":177},[167,330,331],{"class":278},"${DB_PORT}\n",[167,333,335,338,340],{"class":169,"line":334},10,[167,336,337],{"class":256},"      DB_DATABASE",[167,339,275],{"class":177},[167,341,342],{"class":278},"${DB_DATABASE}\n",[167,344,346,349,351],{"class":169,"line":345},11,[167,347,348],{"class":256},"      DB_USERNAME",[167,350,275],{"class":177},[167,352,353],{"class":278},"${DB_USERNAME}\n",[167,355,357,360,362],{"class":169,"line":356},12,[167,358,359],{"class":256},"      DB_PASSWORD",[167,361,275],{"class":177},[167,363,364],{"class":278},"${DB_PASSWORD}\n",[167,366,368,371],{"class":169,"line":367},13,[167,369,370],{"class":256},"    volumes",[167,372,260],{"class":177},[167,374,376,378],{"class":169,"line":375},14,[167,377,291],{"class":177},[167,379,380],{"class":278},"benchkit-runs:/var/www/html/storage/app/runs\n",[167,382,384],{"class":169,"line":383},15,[167,385,386],{"class":234},"    # See \"Why the app container needs more ports\" below\n",[167,388,390,393],{"class":169,"line":389},16,[167,391,392],{"class":256},"    sysctls",[167,394,260],{"class":177},[167,396,398,401,403],{"class":169,"line":397},17,[167,399,400],{"class":256},"      net.ipv4.tcp_tw_reuse",[167,402,275],{"class":177},[167,404,406],{"class":405},"sDLfK","1\n",[167,408,410,413,415],{"class":169,"line":409},18,[167,411,412],{"class":256},"      net.ipv4.ip_local_port_range",[167,414,275],{"class":177},[167,416,417],{"class":278},"\"1024 65535\"\n",[167,419,421,424],{"class":169,"line":420},19,[167,422,423],{"class":256},"    depends_on",[167,425,260],{"class":177},[167,427,429,432],{"class":169,"line":428},20,[167,430,431],{"class":256},"      mysql",[167,433,260],{"class":177},[167,435,437,440,442],{"class":169,"line":436},21,[167,438,439],{"class":256},"        condition",[167,441,275],{"class":177},[167,443,444],{"class":278},"service_healthy\n",[167,446,448],{"class":169,"line":447},22,[167,449,228],{"emptyLinePlaceholder":227},[167,451,453,456],{"class":169,"line":452},23,[167,454,455],{"class":256},"  mysql",[167,457,260],{"class":177},[167,459,461,463,465],{"class":169,"line":460},24,[167,462,272],{"class":256},[167,464,275],{"class":177},[167,466,467],{"class":278},"mysql:8.4\n",[167,469,471],{"class":169,"line":470},25,[167,472,473],{"class":234},"    # Keep above the PHP worker count\n",[167,475,477,480,483,486],{"class":169,"line":476},26,[167,478,479],{"class":256},"    command",[167,481,482],{"class":177},": [",[167,484,485],{"class":278},"\"--max-connections=256\"",[167,487,488],{"class":177},"]\n",[167,490,492,494],{"class":169,"line":491},27,[167,493,299],{"class":256},[167,495,260],{"class":177},[167,497,499,502,504],{"class":169,"line":498},28,[167,500,501],{"class":256},"      MYSQL_DATABASE",[167,503,275],{"class":177},[167,505,342],{"class":278},[167,507,509,512,514],{"class":169,"line":508},29,[167,510,511],{"class":256},"      MYSQL_USER",[167,513,275],{"class":177},[167,515,353],{"class":278},[167,517,519,522,524],{"class":169,"line":518},30,[167,520,521],{"class":256},"      MYSQL_PASSWORD",[167,523,275],{"class":177},[167,525,364],{"class":278},[167,527,529,532,534],{"class":169,"line":528},31,[167,530,531],{"class":256},"      MYSQL_ROOT_PASSWORD",[167,533,275],{"class":177},[167,535,536],{"class":278},"${DB_ROOT_PASSWORD}\n",[167,538,540,542],{"class":169,"line":539},32,[167,541,370],{"class":256},[167,543,260],{"class":177},[167,545,547,549],{"class":169,"line":546},33,[167,548,291],{"class":177},[167,550,551],{"class":278},"mysql-data:/var/lib/mysql\n",[167,553,555,558],{"class":169,"line":554},34,[167,556,557],{"class":256},"    healthcheck",[167,559,260],{"class":177},[167,561,563,566,568,571,574,577,579,582,584,587,589,592],{"class":169,"line":562},35,[167,564,565],{"class":256},"      test",[167,567,482],{"class":177},[167,569,570],{"class":278},"\"CMD\"",[167,572,573],{"class":177},", ",[167,575,576],{"class":278},"\"mysqladmin\"",[167,578,573],{"class":177},[167,580,581],{"class":278},"\"ping\"",[167,583,573],{"class":177},[167,585,586],{"class":278},"\"-h\"",[167,588,573],{"class":177},[167,590,591],{"class":278},"\"localhost\"",[167,593,488],{"class":177},[167,595,597,600,602],{"class":169,"line":596},36,[167,598,599],{"class":256},"      interval",[167,601,275],{"class":177},[167,603,604],{"class":278},"5s\n",[167,606,608,611,613],{"class":169,"line":607},37,[167,609,610],{"class":256},"      timeout",[167,612,275],{"class":177},[167,614,604],{"class":278},[167,616,618,621,623],{"class":169,"line":617},38,[167,619,620],{"class":256},"      retries",[167,622,275],{"class":177},[167,624,625],{"class":405},"10\n",[167,627,629],{"class":169,"line":628},39,[167,630,228],{"emptyLinePlaceholder":227},[167,632,634,637],{"class":169,"line":633},40,[167,635,636],{"class":256},"volumes",[167,638,260],{"class":177},[167,640,642,645],{"class":169,"line":641},41,[167,643,644],{"class":256},"  benchkit-runs",[167,646,260],{"class":177},[167,648,650,653],{"class":169,"line":649},42,[167,651,652],{"class":256},"  mysql-data",[167,654,260],{"class":177},[150,656,659],{"icon":657,"label":658},"i-simple-icons-mariadb","MariaDB",[155,660,661,713],{"default-value":116},[158,662,664],{"className":160,"code":663,"filename":116,"language":162,"meta":163,"style":163},"DB_CONNECTION=mariadb\nDB_HOST=mariadb\nDB_PORT=3306\nDB_DATABASE=benchkit\nDB_USERNAME=benchkit\nDB_PASSWORD=benchkit_secret\n\nDB_ROOT_PASSWORD=root_secret\n",[114,665,666,673,679,685,691,697,703,707],{"__ignoreMap":163},[167,667,668,670],{"class":169,"line":170},[167,669,174],{"class":173},[167,671,672],{"class":177},"=mariadb\n",[167,674,675,677],{"class":169,"line":181},[167,676,184],{"class":173},[167,678,672],{"class":177},[167,680,681,683],{"class":169,"line":189},[167,682,192],{"class":173},[167,684,195],{"class":177},[167,686,687,689],{"class":169,"line":198},[167,688,201],{"class":173},[167,690,204],{"class":177},[167,692,693,695],{"class":169,"line":207},[167,694,210],{"class":173},[167,696,204],{"class":177},[167,698,699,701],{"class":169,"line":215},[167,700,218],{"class":173},[167,702,221],{"class":177},[167,704,705],{"class":169,"line":224},[167,706,228],{"emptyLinePlaceholder":227},[167,708,709,711],{"class":169,"line":231},[167,710,241],{"class":173},[167,712,244],{"class":177},[158,714,716],{"className":247,"code":715,"filename":136,"language":249,"meta":163,"style":163},"services:\n  benchkit:\n    image: serversideup/benchkit-laravel:latest\n    ports:\n      - \"80:8080\"\n    environment:\n      DB_CONNECTION: ${DB_CONNECTION}\n      DB_HOST: ${DB_HOST}\n      DB_PORT: ${DB_PORT}\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n    volumes:\n      - benchkit-runs:/var/www/html/storage/app/runs\n    # See \"Why the app container needs more ports\" below\n    sysctls:\n      net.ipv4.tcp_tw_reuse: 1\n      net.ipv4.ip_local_port_range: \"1024 65535\"\n    depends_on:\n      mariadb:\n        condition: service_healthy\n\n  mariadb:\n    image: mariadb:11.4\n    # Keep above the PHP worker count\n    command: [\"--max-connections=256\"]\n    environment:\n      MARIADB_DATABASE: ${DB_DATABASE}\n      MARIADB_USER: ${DB_USERNAME}\n      MARIADB_PASSWORD: ${DB_PASSWORD}\n      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}\n    volumes:\n      - mariadb-data:/var/lib/mysql\n    healthcheck:\n      test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n      interval: 5s\n      timeout: 5s\n      retries: 10\n\nvolumes:\n  benchkit-runs:\n  mariadb-data:\n",[114,717,718,724,730,738,744,750,756,764,772,780,788,796,804,810,816,820,826,834,842,848,855,863,867,874,883,887,897,903,912,921,930,939,945,952,958,983,991,999,1007,1011,1017,1023],{"__ignoreMap":163},[167,719,720,722],{"class":169,"line":170},[167,721,257],{"class":256},[167,723,260],{"class":177},[167,725,726,728],{"class":169,"line":181},[167,727,265],{"class":256},[167,729,260],{"class":177},[167,731,732,734,736],{"class":169,"line":189},[167,733,272],{"class":256},[167,735,275],{"class":177},[167,737,279],{"class":278},[167,739,740,742],{"class":169,"line":198},[167,741,284],{"class":256},[167,743,260],{"class":177},[167,745,746,748],{"class":169,"line":207},[167,747,291],{"class":177},[167,749,294],{"class":278},[167,751,752,754],{"class":169,"line":215},[167,753,299],{"class":256},[167,755,260],{"class":177},[167,757,758,760,762],{"class":169,"line":224},[167,759,306],{"class":256},[167,761,275],{"class":177},[167,763,311],{"class":278},[167,765,766,768,770],{"class":169,"line":231},[167,767,316],{"class":256},[167,769,275],{"class":177},[167,771,321],{"class":278},[167,773,774,776,778],{"class":169,"line":238},[167,775,326],{"class":256},[167,777,275],{"class":177},[167,779,331],{"class":278},[167,781,782,784,786],{"class":169,"line":334},[167,783,337],{"class":256},[167,785,275],{"class":177},[167,787,342],{"class":278},[167,789,790,792,794],{"class":169,"line":345},[167,791,348],{"class":256},[167,793,275],{"class":177},[167,795,353],{"class":278},[167,797,798,800,802],{"class":169,"line":356},[167,799,359],{"class":256},[167,801,275],{"class":177},[167,803,364],{"class":278},[167,805,806,808],{"class":169,"line":367},[167,807,370],{"class":256},[167,809,260],{"class":177},[167,811,812,814],{"class":169,"line":375},[167,813,291],{"class":177},[167,815,380],{"class":278},[167,817,818],{"class":169,"line":383},[167,819,386],{"class":234},[167,821,822,824],{"class":169,"line":389},[167,823,392],{"class":256},[167,825,260],{"class":177},[167,827,828,830,832],{"class":169,"line":397},[167,829,400],{"class":256},[167,831,275],{"class":177},[167,833,406],{"class":405},[167,835,836,838,840],{"class":169,"line":409},[167,837,412],{"class":256},[167,839,275],{"class":177},[167,841,417],{"class":278},[167,843,844,846],{"class":169,"line":420},[167,845,423],{"class":256},[167,847,260],{"class":177},[167,849,850,853],{"class":169,"line":428},[167,851,852],{"class":256},"      mariadb",[167,854,260],{"class":177},[167,856,857,859,861],{"class":169,"line":436},[167,858,439],{"class":256},[167,860,275],{"class":177},[167,862,444],{"class":278},[167,864,865],{"class":169,"line":447},[167,866,228],{"emptyLinePlaceholder":227},[167,868,869,872],{"class":169,"line":452},[167,870,871],{"class":256},"  mariadb",[167,873,260],{"class":177},[167,875,876,878,880],{"class":169,"line":460},[167,877,272],{"class":256},[167,879,275],{"class":177},[167,881,882],{"class":278},"mariadb:11.4\n",[167,884,885],{"class":169,"line":470},[167,886,473],{"class":234},[167,888,889,891,893,895],{"class":169,"line":476},[167,890,479],{"class":256},[167,892,482],{"class":177},[167,894,485],{"class":278},[167,896,488],{"class":177},[167,898,899,901],{"class":169,"line":491},[167,900,299],{"class":256},[167,902,260],{"class":177},[167,904,905,908,910],{"class":169,"line":498},[167,906,907],{"class":256},"      MARIADB_DATABASE",[167,909,275],{"class":177},[167,911,342],{"class":278},[167,913,914,917,919],{"class":169,"line":508},[167,915,916],{"class":256},"      MARIADB_USER",[167,918,275],{"class":177},[167,920,353],{"class":278},[167,922,923,926,928],{"class":169,"line":518},[167,924,925],{"class":256},"      MARIADB_PASSWORD",[167,927,275],{"class":177},[167,929,364],{"class":278},[167,931,932,935,937],{"class":169,"line":528},[167,933,934],{"class":256},"      MARIADB_ROOT_PASSWORD",[167,936,275],{"class":177},[167,938,536],{"class":278},[167,940,941,943],{"class":169,"line":539},[167,942,370],{"class":256},[167,944,260],{"class":177},[167,946,947,949],{"class":169,"line":546},[167,948,291],{"class":177},[167,950,951],{"class":278},"mariadb-data:/var/lib/mysql\n",[167,953,954,956],{"class":169,"line":554},[167,955,557],{"class":256},[167,957,260],{"class":177},[167,959,960,962,964,966,968,971,973,976,978,981],{"class":169,"line":562},[167,961,565],{"class":256},[167,963,482],{"class":177},[167,965,570],{"class":278},[167,967,573],{"class":177},[167,969,970],{"class":278},"\"healthcheck.sh\"",[167,972,573],{"class":177},[167,974,975],{"class":278},"\"--connect\"",[167,977,573],{"class":177},[167,979,980],{"class":278},"\"--innodb_initialized\"",[167,982,488],{"class":177},[167,984,985,987,989],{"class":169,"line":596},[167,986,599],{"class":256},[167,988,275],{"class":177},[167,990,604],{"class":278},[167,992,993,995,997],{"class":169,"line":607},[167,994,610],{"class":256},[167,996,275],{"class":177},[167,998,604],{"class":278},[167,1000,1001,1003,1005],{"class":169,"line":617},[167,1002,620],{"class":256},[167,1004,275],{"class":177},[167,1006,625],{"class":405},[167,1008,1009],{"class":169,"line":628},[167,1010,228],{"emptyLinePlaceholder":227},[167,1012,1013,1015],{"class":169,"line":633},[167,1014,636],{"class":256},[167,1016,260],{"class":177},[167,1018,1019,1021],{"class":169,"line":641},[167,1020,644],{"class":256},[167,1022,260],{"class":177},[167,1024,1025,1028],{"class":169,"line":649},[167,1026,1027],{"class":256},"  mariadb-data",[167,1029,260],{"class":177},[150,1031,1034],{"icon":1032,"label":1033},"i-simple-icons-postgresql","PostgreSQL",[155,1035,1036,1080],{"default-value":116},[158,1037,1039],{"className":160,"code":1038,"filename":116,"language":162,"meta":163,"style":163},"DB_CONNECTION=pgsql\nDB_HOST=postgres\nDB_PORT=5432\nDB_DATABASE=benchkit\nDB_USERNAME=benchkit\nDB_PASSWORD=benchkit_secret\n",[114,1040,1041,1048,1055,1062,1068,1074],{"__ignoreMap":163},[167,1042,1043,1045],{"class":169,"line":170},[167,1044,174],{"class":173},[167,1046,1047],{"class":177},"=pgsql\n",[167,1049,1050,1052],{"class":169,"line":181},[167,1051,184],{"class":173},[167,1053,1054],{"class":177},"=postgres\n",[167,1056,1057,1059],{"class":169,"line":189},[167,1058,192],{"class":173},[167,1060,1061],{"class":177},"=5432\n",[167,1063,1064,1066],{"class":169,"line":198},[167,1065,201],{"class":173},[167,1067,204],{"class":177},[167,1069,1070,1072],{"class":169,"line":207},[167,1071,210],{"class":173},[167,1073,204],{"class":177},[167,1075,1076,1078],{"class":169,"line":215},[167,1077,218],{"class":173},[167,1079,221],{"class":177},[158,1081,1083],{"className":247,"code":1082,"filename":136,"language":249,"meta":163,"style":163},"services:\n  benchkit:\n    image: serversideup/benchkit-laravel:latest\n    ports:\n      - \"80:8080\"\n    environment:\n      DB_CONNECTION: ${DB_CONNECTION}\n      DB_HOST: ${DB_HOST}\n      DB_PORT: ${DB_PORT}\n      DB_DATABASE: ${DB_DATABASE}\n      DB_USERNAME: ${DB_USERNAME}\n      DB_PASSWORD: ${DB_PASSWORD}\n    volumes:\n      - benchkit-runs:/var/www/html/storage/app/runs\n    # See \"Why the app container needs more ports\" below\n    sysctls:\n      net.ipv4.tcp_tw_reuse: 1\n      net.ipv4.ip_local_port_range: \"1024 65535\"\n    depends_on:\n      postgres:\n        condition: service_healthy\n\n  postgres:\n    image: postgres:18\n    # Keep above the PHP worker count\n    command: [\"postgres\", \"-c\", \"max_connections=256\"]\n    environment:\n      POSTGRES_DB: ${DB_DATABASE}\n      POSTGRES_USER: ${DB_USERNAME}\n      POSTGRES_PASSWORD: ${DB_PASSWORD}\n    volumes:\n      - postgres-data:/var/lib/postgresql/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE}\"]\n      interval: 5s\n      timeout: 5s\n      retries: 10\n\nvolumes:\n  benchkit-runs:\n  postgres-data:\n",[114,1084,1085,1091,1097,1105,1111,1117,1123,1131,1139,1147,1155,1163,1171,1177,1183,1187,1193,1201,1209,1215,1222,1230,1234,1241,1250,1254,1275,1281,1290,1299,1308,1314,1321,1327,1343,1351,1359,1367,1371,1377,1383],{"__ignoreMap":163},[167,1086,1087,1089],{"class":169,"line":170},[167,1088,257],{"class":256},[167,1090,260],{"class":177},[167,1092,1093,1095],{"class":169,"line":181},[167,1094,265],{"class":256},[167,1096,260],{"class":177},[167,1098,1099,1101,1103],{"class":169,"line":189},[167,1100,272],{"class":256},[167,1102,275],{"class":177},[167,1104,279],{"class":278},[167,1106,1107,1109],{"class":169,"line":198},[167,1108,284],{"class":256},[167,1110,260],{"class":177},[167,1112,1113,1115],{"class":169,"line":207},[167,1114,291],{"class":177},[167,1116,294],{"class":278},[167,1118,1119,1121],{"class":169,"line":215},[167,1120,299],{"class":256},[167,1122,260],{"class":177},[167,1124,1125,1127,1129],{"class":169,"line":224},[167,1126,306],{"class":256},[167,1128,275],{"class":177},[167,1130,311],{"class":278},[167,1132,1133,1135,1137],{"class":169,"line":231},[167,1134,316],{"class":256},[167,1136,275],{"class":177},[167,1138,321],{"class":278},[167,1140,1141,1143,1145],{"class":169,"line":238},[167,1142,326],{"class":256},[167,1144,275],{"class":177},[167,1146,331],{"class":278},[167,1148,1149,1151,1153],{"class":169,"line":334},[167,1150,337],{"class":256},[167,1152,275],{"class":177},[167,1154,342],{"class":278},[167,1156,1157,1159,1161],{"class":169,"line":345},[167,1158,348],{"class":256},[167,1160,275],{"class":177},[167,1162,353],{"class":278},[167,1164,1165,1167,1169],{"class":169,"line":356},[167,1166,359],{"class":256},[167,1168,275],{"class":177},[167,1170,364],{"class":278},[167,1172,1173,1175],{"class":169,"line":367},[167,1174,370],{"class":256},[167,1176,260],{"class":177},[167,1178,1179,1181],{"class":169,"line":375},[167,1180,291],{"class":177},[167,1182,380],{"class":278},[167,1184,1185],{"class":169,"line":383},[167,1186,386],{"class":234},[167,1188,1189,1191],{"class":169,"line":389},[167,1190,392],{"class":256},[167,1192,260],{"class":177},[167,1194,1195,1197,1199],{"class":169,"line":397},[167,1196,400],{"class":256},[167,1198,275],{"class":177},[167,1200,406],{"class":405},[167,1202,1203,1205,1207],{"class":169,"line":409},[167,1204,412],{"class":256},[167,1206,275],{"class":177},[167,1208,417],{"class":278},[167,1210,1211,1213],{"class":169,"line":420},[167,1212,423],{"class":256},[167,1214,260],{"class":177},[167,1216,1217,1220],{"class":169,"line":428},[167,1218,1219],{"class":256},"      postgres",[167,1221,260],{"class":177},[167,1223,1224,1226,1228],{"class":169,"line":436},[167,1225,439],{"class":256},[167,1227,275],{"class":177},[167,1229,444],{"class":278},[167,1231,1232],{"class":169,"line":447},[167,1233,228],{"emptyLinePlaceholder":227},[167,1235,1236,1239],{"class":169,"line":452},[167,1237,1238],{"class":256},"  postgres",[167,1240,260],{"class":177},[167,1242,1243,1245,1247],{"class":169,"line":460},[167,1244,272],{"class":256},[167,1246,275],{"class":177},[167,1248,1249],{"class":278},"postgres:18\n",[167,1251,1252],{"class":169,"line":470},[167,1253,473],{"class":234},[167,1255,1256,1258,1260,1263,1265,1268,1270,1273],{"class":169,"line":476},[167,1257,479],{"class":256},[167,1259,482],{"class":177},[167,1261,1262],{"class":278},"\"postgres\"",[167,1264,573],{"class":177},[167,1266,1267],{"class":278},"\"-c\"",[167,1269,573],{"class":177},[167,1271,1272],{"class":278},"\"max_connections=256\"",[167,1274,488],{"class":177},[167,1276,1277,1279],{"class":169,"line":491},[167,1278,299],{"class":256},[167,1280,260],{"class":177},[167,1282,1283,1286,1288],{"class":169,"line":498},[167,1284,1285],{"class":256},"      POSTGRES_DB",[167,1287,275],{"class":177},[167,1289,342],{"class":278},[167,1291,1292,1295,1297],{"class":169,"line":508},[167,1293,1294],{"class":256},"      POSTGRES_USER",[167,1296,275],{"class":177},[167,1298,353],{"class":278},[167,1300,1301,1304,1306],{"class":169,"line":518},[167,1302,1303],{"class":256},"      POSTGRES_PASSWORD",[167,1305,275],{"class":177},[167,1307,364],{"class":278},[167,1309,1310,1312],{"class":169,"line":528},[167,1311,370],{"class":256},[167,1313,260],{"class":177},[167,1315,1316,1318],{"class":169,"line":539},[167,1317,291],{"class":177},[167,1319,1320],{"class":278},"postgres-data:/var/lib/postgresql/data\n",[167,1322,1323,1325],{"class":169,"line":546},[167,1324,557],{"class":256},[167,1326,260],{"class":177},[167,1328,1329,1331,1333,1336,1338,1341],{"class":169,"line":554},[167,1330,565],{"class":256},[167,1332,482],{"class":177},[167,1334,1335],{"class":278},"\"CMD-SHELL\"",[167,1337,573],{"class":177},[167,1339,1340],{"class":278},"\"pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE}\"",[167,1342,488],{"class":177},[167,1344,1345,1347,1349],{"class":169,"line":562},[167,1346,599],{"class":256},[167,1348,275],{"class":177},[167,1350,604],{"class":278},[167,1352,1353,1355,1357],{"class":169,"line":596},[167,1354,610],{"class":256},[167,1356,275],{"class":177},[167,1358,604],{"class":278},[167,1360,1361,1363,1365],{"class":169,"line":607},[167,1362,620],{"class":256},[167,1364,275],{"class":177},[167,1366,625],{"class":405},[167,1368,1369],{"class":169,"line":617},[167,1370,228],{"emptyLinePlaceholder":227},[167,1372,1373,1375],{"class":169,"line":628},[167,1374,636],{"class":256},[167,1376,260],{"class":177},[167,1378,1379,1381],{"class":169,"line":633},[167,1380,644],{"class":256},[167,1382,260],{"class":177},[167,1384,1385,1388],{"class":169,"line":641},[167,1386,1387],{"class":256},"  postgres-data",[167,1389,260],{"class":177},[102,1391,1392],{},"Then bring both containers up:",[158,1394,1399],{"className":1395,"code":1396,"filename":1397,"language":1398,"meta":163,"style":163},"language-bash shiki shiki-themes github-dark","docker compose up -d\n","Terminal","bash",[114,1400,1401],{"__ignoreMap":163},[167,1402,1403,1407,1410,1413],{"class":169,"line":170},[167,1404,1406],{"class":1405},"svObZ","docker",[167,1408,1409],{"class":278}," compose",[167,1411,1412],{"class":278}," up",[167,1414,1415],{"class":405}," -d\n",[1417,1418,1419],"note",{},[102,1420,1421,1423,1424,1427,1428,1430],{},[114,1422,184],{}," is the service name from the compose file rather than ",[114,1425,1426],{},"localhost",". Containers reach each other by service name on the Compose network, and ",[114,1429,1426],{}," inside the BenchKit container means the BenchKit container itself.",[102,1432,1433,1434,1437],{},"The healthcheck on ",[114,1435,1436],{},"depends_on"," is what keeps your first run honest. Database images accept connections shortly before they are ready to serve them well, and a benchmark that starts in that window measures the warmup rather than the database.",[106,1439,1441],{"id":1440},"why-the-connection-limit-is-raised","Why the connection limit is raised",[102,1443,1444],{},"Every database image ships a connection limit meant for ordinary traffic, and a load test is not ordinary traffic. Every request in flight holds one database connection, so the database needs at least as many connections as the app has workers — on a pool of a few hundred, the stock limit is reached partway through the sweep and the DB route starts failing while it is still gaining throughput.",[102,1446,1447],{},"The figure above covers the default pool with room to raise it. The rule is that it must stay above the worker count shown in the Environment panel, so if you size the pool up, size this up with it. If your results page reports that the DB read route broke at some number of connections, it says which of these limits it was.",[102,1449,1450],{},"On Postgres each connection is a separate process, so a very high limit costs memory. Size it to your worker count rather than reaching for the largest number that works.",[106,1452,1454],{"id":1453},"why-the-app-container-needs-more-ports","Why the app container needs more ports",[102,1456,1457],{},"Under PHP-FPM every request on the DB route opens a connection to the database and closes it when the request ends. A closed TCP connection holds its source port for a minute afterwards, and a container has about 28,000 source ports to draw from. A host serving a few hundred DB requests a second uses them all partway up the sweep, and from there every new connection fails before it reaches the database. The route answers 503, the database's own log stays empty, and no connection limit on the database side changes it.",[102,1459,1460,1461,1464,1465,1468,1469,1472],{},"The two ",[114,1462,1463],{},"sysctls"," in the compose files above are the fix. ",[114,1466,1467],{},"tcp_tw_reuse"," lets the kernel hand a port that is still waiting out its minute to a new outbound connection after one second, and the wider ",[114,1470,1471],{},"ip_local_port_range"," doubles the pool. Both apply to the app container alone and need no privileges on the host.",[106,1474,1476],{"id":1475},"what-a-connection-costs-on-each-serving-model","What a connection costs on each serving model",[102,1478,1479,1480,1483],{},"How long a connection lives depends on how PHP is served, and it shows on the ",[114,1481,1482],{},"/bench/db-read"," route. Under PHP-FPM a connection is opened when a request starts and closed when it ends, so every request on that route pays a connection setup. In worker mode the application stays resident and its connection with it, so requests after the first pay nothing.",[102,1485,1486],{},"On MySQL and MariaDB that setup is cheap. On Postgres each new connection is a forked server process, so an FPM run against Postgres carries real connection cost on the DB route that a worker-mode run against the same database does not. That is honest — it is how an application on FPM without a connection pooler behaves — but when you compare the two variations on that route, part of the gap is connection cost rather than query speed. The other three routes never touch the database and are unaffected.",[106,1488,1490],{"id":1489},"on-a-host-without-docker","On a host without Docker",[102,1492,1493,1494,1498,1499,1501],{},"If you are ",[1495,1496,1497],"a",{"href":22},"running from source",", there is no compose file involved. Set the same ",[114,1500,140],{}," variables however your platform manages environment variables, and point them at a database it can reach.",[106,1503,1505],{"id":1504},"there-is-no-migration-step","There is no migration step",[102,1507,1508,1509,1512],{},"BenchKit creates the tables it benchmarks when it needs them, and drops them afterwards. You do not run ",[114,1510,1511],{},"artisan migrate"," and there is no seeder to run. Point BenchKit at a database it can reach, and the database route and the PHP stage use it on the next run.",[1417,1514,1515],{},[102,1516,1517],{},"Your run history is stored as files rather than in the database. Changing the database engine only changes what the benchmark measures. Your saved runs are unaffected.",[1519,1520,1521],"tip",{},[102,1522,1523],{},"The environment panel on a result records which database engine produced it. A MySQL run and a SQLite run are never confused with each other when you compare them later.",[1525,1526,1527],"style",{},"html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}",{"title":163,"searchDepth":181,"depth":181,"links":1529},[1530,1531,1532,1533,1534,1535],{"id":108,"depth":181,"text":109},{"id":1440,"depth":181,"text":1441},{"id":1453,"depth":181,"text":1454},{"id":1475,"depth":181,"text":1476},{"id":1489,"depth":181,"text":1490},{"id":1504,"depth":181,"text":1505},"Point BenchKit at MySQL, MariaDB, or Postgres instead of the default SQLite.","md",null,{},{"title":48,"description":1536},{"loc":49},"O8QMCqdhgsuQD1keZzEtT9LNbqHmr_c7yE0hvTHh-7Y",[1544,1546],{"title":37,"path":38,"stem":39,"description":1545,"children":-1},"Pair a second machine to drive the load test, or point oha at the endpoints yourself.",{"title":52,"path":53,"stem":54,"description":1547,"children":-1},"Tune PHP, OPcache, and the web server with environment variables, or add your own php.ini.",1790284380233]