Earlier this week, I finally (after long and hard work) pushed the Zend_Http_Client out of the incubator and into the core of Zend Framework, and it will be released with the 0.6 preview release.
Now that it’s mostly done, I had some time to do some benchmarking. But first, maybe a short explanation about the new client’s adapter architecture:
One of the things we introduced in the new client is the “connection adapters”: The idea is that there is a different object in charge of performing the actual communication with the server. This “adapter” object can be replaced, and this way you get the same interface (the Zend_Http_Client interface), with a different method to connect to the server.
For example, the default adapter is a socket based adapter, implemented entirely in PHP with no dependency of any special extension. However, Stefan Koopmanschap has been working on a new adapter, based on the Curl extension. The reason is that apparently some hosting providers disable the fsockopen() function, but allow the use of Curl (for some vague “security” reasons I guess…). By replacing the Socket adapter with the Curl adapter, people could use the same API but work around the fsockopen() function. The Curl adapter is still in the incubator.
We also have a Test adapter, that can be used to create mock Zend_Http_Client objects for testing purposes.
Additionally, there are some ideas for additional adapters that might be written some day: A caching adapter, that will only send requests if the item was not already found in cache, or a pfsockopen() based adapter, which is basically a slight modification of the Socket adapter, only connections are persistent.
So, playing around with the idea of a pfsockopen() based adapter, I decided to run a little benchmark, checking how much performance people might gain from the idea. The benchmark I run was very simple: I created a test script, fetching 4 different files from the same HTTP server, with 3 different settings: First, with the default Socket based adapter. Second, with the Socket adapter with keep-alive connections turned on. Third, I slightly modified the Socket adapter to use pfsockopen() instead of fsockopen(), and to not close connections. I ran a benchmarking suite, calling the test script as many times as possible in 60 seconds.
Here are the results:
|Adapter||Total requests||avg. requests / sec.||Improvement (%)|
|Socket + Keepalive||34||0.57||35%|
Put in a graph, it looks like this:
This is pretty interesting. It seems that in some situations, using keep-alive and persistent connections could be a smart idea. It is important to say that the benchmark was run over the “real” internet, but the results were pretty stable (I ran each benchmark several times). I would guess that over faster networks, the PSocket based adapter would have an even greater benefit – as the relative overhead of opening and closing connections would be greater.
However, this is not good for everyone. I would generally say that persistent sockets are only good if you do allot of HTTP connections (that is on almost every page of your application, or at least on the popular ones), and that most of your connections go to the same server.
If this is not your case, I would recommend using the Socket based adapter. Persistent sockets, if you don’t use them, are held open by your Apache process for nothing – just waisting resources. Additionally, you are keeping a connection open for nothing on the other side – and that’s just a mean thing to do
If you don’t perform allot of requests, but do perform more than one request to the same server on a single script, you probably want to use the Socket adapter with the keep-alive option turned on.
If you just perform a single, occasional request, or perform more than one request but not to the same server, you should use the Socket adapter with keep-alive turned off: you will get the same performance, but the connection will be closed when the request is finished – so both you and your peer server save resources.