Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

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

share|improve this question
    
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? –  jon Jan 15 '12 at 22:55

1 Answer 1

up vote 4 down vote accepted

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.)

share|improve this answer
    
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 6:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.