4

I have a server with Dual Xeon Quad Core L5420 running at 2.5GHz. I've been optimizing my server, and have come to my final bottleneck: PHP.

My very simple PHP script:

./test.php

<?php print_r(posix_getpwuid(posix_getuid()));

My not-so-scientific-because-they-don't-pay-attention-to-thread-locking-but-scientific-enough-to-give-me-a-reasonable-multithreaded-requests-per-second-result scripts:

./benchmark-php

#!/bin/bash
if [ -z $1 ]; then
  LIMIT=10
else
  LIMIT=$1
fi

if [ -z $2 ]; then
  SCRIPT="index.php"
else
  SCRIPT=$2
fi

START=$(date +%s.%N)
COUNT=0
while (( $COUNT < $LIMIT ))
do
  php $SCRIPT > /dev/null
  COUNT=$(echo "$COUNT + 1" | bc)
done
END=$(date +%s.%N)
DIFF=$(echo "$END - $START" | bc)
REQS_PER_SEC=$(echo "scale=2; $COUNT / $DIFF" | bc)
echo $REQS_PER_SEC

./really-benchmark-php

#!/bin/bash
if [ -z $1 ]; then
  LIMIT=10
else
  LIMIT=$1
fi

if [ -z $2 ]; then
  THREADS=16
else
  THREADS=$2
fi

if [ -z $3 ]; then
  SCRIPT="index.php"
else
  SCRIPT=$3
fi

PIDS=""

echo '' > results
for thread in `seq 1 $THREADS`; do
  ./benchmark-php $LIMIT $SCRIPT >> results &
  PIDS="$PIDS $!"
done

for PID in $PIDS; do
  wait $PID
done

RESULTS=`cat results`
MATH="0"
for RESULT in $RESULTS; do
  MATH="$MATH + $RESULT"
done

echo "$MATH" | bc

The result of running ./really-benchmark-php 100 8 test.php is ~137 requests per second.

Running the same script on a sqlite or mysql powered instance of Drupal returns ~1.5 req/s.

I have APC and mem_cache both installed, and I have verified that they're running on defaults. (Yes, APC's enable_cli is on, also.) Does someone know the magic "make PHP execute faster" switch?

I have an alternative configuration setup (FPM/FastCGI) that serves ~140 req/s of the MySQL Drupal install... how could that be possible if PHP itself can't even serve 2 req/s from the command line?

The result of the ab tool feel just as low to me:

static page: ab -n 1000 -c 100 http://x.x.x.x/ Requests per second: 683.71

test php: ab -n 100 -c 5 http://x.x.x.x/ Requests per second: 41.38

drupal-mysql: ab -n 100 -c 10 http://x.x.x.x/drupal/ Requests per second: 0.24

drupal-sqlite: ab -n 100 -c 10 http://x.x.x.x/drupal-test/ Requests per second: 4.92

  • Is there some reason why you are using bc in a bash script to do your arithmatic? Bash can do math on its own, right now that script is opening tons of sub-processes. – Zoredache Jan 12 '12 at 23:48
  • Bash can't do floating point math. BC allows me to use decimals for more numbers. The scripts are simple: "benchmark-php" just runs the php script a certain number of times, "really-benchmark-php" runs "benchmark-php" in a certain number of processes. Basically, I wanted to emulate, on a CLI level, what Apache does when handling requests. It is purely to determine the maximum speed I should expect from PHP. The fact that it only runs an extremely simple test ~137 time a second over 8 cores disturbs me. I've written faster Bash scripts. – Caleb Gray Jan 13 '12 at 16:15
  • I'm a little confused about which tests get which speeds... I think it's: command-line test.php is 137/s; command-line drupal is 1.5/s. The FPM/FastCGI benchmark is the same instance of drupal as the one you used on the command-line. All the ab benchmarks are against the same server. The http://drupal one is against the same drupal instance as before, and drupal-test is the second drupal instance. Yes? – jade Jan 15 '12 at 22:55

1 Answers1

4

If you're launching PHP from the command line, each run needs to load the entire PHP interpreter, all required libraries, files, etc. That has a huge overhead.

If your web server is configured to do the same thing, then the magic "make PHP faster switch" is probably switching to using mod_php, FastCGI, or something similar, which lets a single PHP interpreter serve multiple requests. (Note that each interpreter can only serve one request simultaneously; the responsibility of launching multiple PHP interpreters lies with your web server for mod_php or whatever's launching your FastCGI thing.)

jade
  • 890
  • 5
  • 15
  • Thank you for the plain English. It occurred to me that what you've said above could have been the problem all along, and so I have gone back to tweaking my PHP-FPM setup, which is very, very fast. :) – Caleb Gray Jan 16 '12 at 06:22