[Info-vax] Apache + mod_php performance

Dan Cross cross at spitfire.i.gajendra.net
Wed Oct 2 10:29:27 EDT 2024


In article <vdji17$38hdb$1 at dont-email.me>,
Dave Froble  <davef at tsoft-inc.com> wrote:
>On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
>> On 10/1/2024 3:45 PM, Dan Cross wrote:
>>> In article <vd9mqn$1cm1v$1 at dont-email.me>,
>>> Dave Froble  <davef at tsoft-inc.com> wrote:
>>>> On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
>>>> [snip]
>>>>> I believe that server config supporting keep alive
>>>>> causing performance to drop to 1/10'th for clients
>>>>> not using keep alive is a bug.
>>>>
>>>> Feature ...
>>>
>>> Yes, it is a feature, despite this report of a non-problem.
>>>
>>> In this case, later posts revealed the real culprit: Arne's test
>>> program did not follow the protocol, and was not sending
>>> `Connection: close` with an HTTP/1.1 request; in response, the
>>> server (correctly) kept the connection open waiting for the
>>> client to send another request.
>>
>> It does not really make any sense for the test client
>> to send "Connection: close".
>
>It does if the server is holding the connection open, waiting for more.

Which is precisely the behavior Arne observed, and is also what
the RFC says the server should do.

>Not claiming this happens in the real world.  Things aren't that clean.

I decided to do what Arne was either unwilling or unable to do:
connect to the server directly and observe its behavior.  This
is an example of the sort of problem report that Arne _should_
have sent; had he given some useful details on the experimental
setup he used, and his observed results, we probably could have
been able to see his error much earlier, but he was rather
cagey with details and this conversation dragged on.  Anyway.

I did not set Apache up under VMS, but instead, did so on
FreeBSD.  Everything is stock; installation was just via the
normal `pkg install apache24`.

I then created a simple text file under apache's DocumentRoot:

```
: fbsd; cat /usr/local/www/apache24/data/nop.txt
hi
: fbsd;
```

I verified that I could get that via `curl`:

```
: fbsd; curl http://localhost/nop.txt
hi
: fbsd;
```

(Note, that returns almost immediately.)

To get a baseline on performance, I used the `ab` tool ("Apache
Bench").  I hit it with 100,000 requests using 20 concurrent
requestors.

```
: fbsd; ab -c 20 -n 100000 http://localhost/nop.txt
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        Apache/2.4.62
Server Hostname:        localhost
Server Port:            80

Document Path:          /nop.txt
Document Length:        3 bytes

Concurrency Level:      20
Time taken for tests:   1.247 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      24900000 bytes
HTML transferred:       300000 bytes
Requests per second:    80200.05 [#/sec] (mean)
Time per request:       0.249 [ms] (mean)
Time per request:       0.012 [ms] (mean, across all concurrent requests)
Transfer rate:          19501.77 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   0.0      0       0
Waiting:        0    0   0.0      0       0
Total:          0    0   0.0      0       0

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      0
  95%      0
  98%      0
  99%      0
 100%      0 (longest request)
: fbsd;
```

I then observed what happened if I connected directly to the
HTTP server and sent commands.  I used the "netcat" (`nc`)
command to connect to the HTTP server port, and issued a
`GET` request via a pipe; I timed the `nc` command to see how
long it took until the server disconnected.

```
: fbsd; (printf "GET /nop.txt HTTP/1.1\r\nHost: localhost\r\n\r\n") | time nc localhost 80
HTTP/1.1 200 OK
Date: Wed, 02 Oct 2024 14:00:42 GMT
Server: Apache/2.4.62 (FreeBSD)
Last-Modified: Wed, 02 Oct 2024 13:44:20 GMT
ETag: "3-6237ea2939a43"
Accept-Ranges: bytes
Content-Length: 3
Content-Type: text/plain

hi
nc localhost 80  0.00s user 0.00s system 0% cpu 5.106 total
: fbsd;
```

My observation was that the resposne to the query returned
almost immediately (within milliseconds), and the server
disconnected around the 5 second mark, as indicated by the
`time` command.

This, and having some familiarity with reading RFCs, makes clear
what is going on: without sending the `Connection: close` header
the server is waiting for the another request; eventually it
times out closes the connection.  Where does the 5 seconds come
from, though?  It's probably a configuration parameter, but let
us see if we can verify.  Using the "ripgrep" tool (`rg`), I
search for the number "5" in the Apache configuration:

```
: fbsd; rg '\b5\b' /usr/local/etc/apache24
[snip]

/usr/local/etc/apache24/extra/httpd-default.conf
29:KeepAliveTimeout 5

[snip]

/usr/local/etc/apache24/extra/httpd-mpm.conf.sample
29:    StartServers             5
30:    MinSpareServers          5
97:    MinSpareThreads          5
: fbsd;
```

I cut out a number of irrelvant matches (magic numbers and MIME
types and the like), but the output isn't that big, and
certainly `KeepAliveTimeout` shines like a bright light in the
middle of it.  That matches our observed results, but what
happens if I change it to, say, 20 seconds?  I edit the config
file and restart the server and re-run my test:

```
: fbsd; (printf "GET /nop.txt HTTP/1.1\r\nHost: localhost\r\n\r\n") | time nc localhost 80
HTTP/1.1 200 OK
Date: Wed, 02 Oct 2024 14:19:50 GMT
Server: Apache/2.4.62 (FreeBSD)
Last-Modified: Wed, 02 Oct 2024 13:44:20 GMT
ETag: "3-6237ea2939a43"
Accept-Ranges: bytes
Content-Length: 3
Content-Type: text/plain

hi
nc localhost 80  0.00s user 0.00s system 0% cpu 20.317 total
: fbsd;
```

And there we have it.  This behavior clearly matches what Arne
saw, and we can speculate that the "problem" that Arne observed
was almost certainly due to the default setting of
`KeepAliveTimeout` on VMS being 20 seconds.  I'd bet cookies to
cake that, if Arne changed that value, he'd see different
timeouts with his test client.

	- Dan C.



More information about the Info-vax mailing list