When serving files with PHP, you may notice a curious effect where only one request gets served at a time per user.
You can see it if you're the kind of retro throwback who uses framesets served via PHP - the panels will load in one at a time. You'll see the same thing if you generate a load of images via PHP - they'll pop up sequentially - and if you serve large video files via PHP like we do at work you may see a curious effect of the downloads queueing up. Those of you with AJAX applications may be victim to this without realising, but if you're serving JSON/XML responses from PHP scripts you'll find that your parallel AJAX requests will only get served one at a time.
I've seen this effect a few times and always ended up working around it. The odd thing is this isn't a setting in Apache or a global slowdown of your server. PHP just refuses to serve more than one request per user at a time. Luckily Kevin managed to spot the reason, and it was a new one on me even after 9+ years of using PHP (it's possible everyone else knows about it, mind you).
The answer is pretty simple: PHP can only handle one response at a time if you have an open session.
This makes perfect sense when you think about it - when you session_start() PHP has to read the data out of the session, then at the end of your script it has to write the data back - if this was happening in parallel then you'd have classic race conditions. To handle this PHP locks the session on session_start() and other pending requests will block until the lock is released.
This leads to some guidelines:
- Don't start sessions with session_start() until you need them (but remember you have to start them before your script output begins). This would also imply not using session.autostart if you can avoid it.
- When serving files via PHP, consider serving them from a different domain so the sessions don't overlap.
- End your sessions as soon as you can. By calling session_write_close() you can release your session lock, so as soon as you know your script won't need to write any more to the session, call it.
Hopefully this will help out somebody in a similar situation in future!