Freelance Projects

Upeksha Wisidagama

Mundane Experiments With Apache Prefork MPM and Mod_PHP

This is an experiment of this earthly world rather than a heavenly or spiritual one. Apache is a popular web server eventhough it can’t solve the C10k Problem.

Prefork (Module Identifier:mpm_prefork_module) is the default Multi Processing Module for Apache Server in Ubuntu.

This Multi-Processing Module (MPM) implements a non-threaded, pre-forking web server. Each server process may answer incoming requests, and a parent process manages the size of the server pool.

The other MPMs are Event and Worker (there are others of course: mpm_netware, mpm_os2, mpm_winnt). Visit Apache Module Index to find out more.

Apache Prefork MPM in Action in Top

I’ve written a How to install a local Ubuntu Server post explaining how I set up a testing server. Now, I am going to use that server for the following experiments.

PHP is loaded as Module by default. Log into your fresh server (described in the above linked article), and run the top command.

Next enable highlighting by pressing z. Then enable column highlighting by pressing x. You can change the sorting of the rows by columns. Just press < and > until you get the required column highlighted. The above figure shows the rows as ordered by ‘Resident Memory (RE)’ they consume. The most Resident Memory consuming process is the mysqld. This is the MySQL daemon, accounting for 33Mbs out of total 1GB RAM.

PID: 1668 is the Apache2 parent process owned by root. It consumes 7Mbs of RAM. Each of the children of Apache2 parent process consumes ~ 4.4Mbs of RAM. But 1MB of RAM is being shared.

How the server decided to spawn 9 children? Let’s see the apache2 configuration files stored in ‘/etc/apache2/’.

‘Apache Prefork MPM Configuration (/etc/apache2/apache2.conf)’
1
2
3
4
5
6
7
8
9
10
11
12
13
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

By default, apache2 starts only 5 child processes(StartServers). I simulated a high traffic scenario using Apache Benchmarking tool (ab). As a resulf of the high traffic, Apache2 increased the number of processes to 9. Next, I restarted the server using sudo service apache2 restart. Then the number of child processes shown was 5. You can change the parameters under mpm_prefork_module to match your client needs and wants.

Next I changed ‘Start’, ‘Min’ and ‘Max’ servers to 1. I even chaged ‘MaxClients’ to 1. I need to run only one apache2 child. See the top output for one apache2 child process (PID: 4227).

Prefork with only one server

Benchmarking Apache Performance with Varing number of Child Processes

Let’s benchmark the performance of Apache with One Child and Five Children with mod_php enabled. We serve a simple html file.

‘index.html’
1
2
3
4
<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>

First, change the Prefork configuration to run only one child as described above.

Run ab -n 1000 -c 10 -g one-child.dat http://192.168.1.8/

Then change Apache Prefork to span five children.

Run ab -n 1000 -c 10 -g five-children.dat http://192.168.1.8/

Then plot the graph. We’ll be using Gnuplot for plotting. Create the Prefork.p

‘Prefork.p’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# output as png image
set terminal png

# save file to "prefork-benchmarking.png"
set output "prefork-benchmarking.png"

# graph title
set title "Apache2 Benchmarking with Prefork MPM"

# nicer aspect ratio for image size
set size 1,0.7

# y-axis grid
set grid y

# x-axis label
set xlabel "request"

# y-axis label
set ylabel "response time (ms)"

#plot data from data files
plot "one-child.dat" using 9 smooth sbezier with lines title "One Child", \
"five-children.dat" using 9 smooth sbezier with lines title "Five Children"

Now plot the data using gnuplot Prefork.p.

Apache2 Prefork Benchmarking with Low Concurrency

The following is the plot when the concurrecy level is set to 100 (use -c 100 instead -c 10 in ab tool).

Apache2 Prefork Benchmarking with High Concurrency

Now you have the basic building blocks of Apache2 benchmarking. You can tweak various parameters, collect data and plot. Observe the plot. Contemplate or even meditate on the data and the visualization of the data. Gnuplot can plot more than two datasets. Infact, it is capable of plotting in 3D. It is also used as a plotting engine by third-party applications like Octave.

Gnuplot was originally created to allow scientists and students to visualize mathematical functions and data interactively, but has grown to support many non-interactive uses such as web scripting.

Relaxation of ‘one-per-second’ Rule - Apache2 Process Creation

As of Apache 1.3, the code will relax the one-per-second rule. It will spawn one, wait a second, then spawn two, wait a second, then spawn four, and it will continue exponentially until it is spawning 32 children per second. It will stop whenever it satisfies the MinSpareServers setting. Read more about Apache2 Performance Tuning.

Happy Apache2 Prefork Benchmarking with or without mod_php!