Apache::Session is easy to use and works great – but it could be a big bottleneck. I developed a huge web application for my company which is – over all requests – slower than it should be. Some earlier analysis told me that the reason might be in the sessioning part. Adding a big ajax-loaded page with many sub-requests during the last days, I started to look at the speed issue again this morning.
Everybody knows that memory is faster than a hard disk. The application is using Apache::Session::SharedMem and even if it’s “shared memory” (which is slower than normal memory due to locking), it must be faster than a hard disk – because it’s memory!
Benchmarking the sessioning is easy:
use Apache::Session::SharedMem;
use Time::HiRes('time');
my $t = time; # Store the start time
for (1..1000) {
my $sid; # session-id
for (1..2) {
# Create a new session (1) or open an existing (2)
tie %Session,"Apache::Session::SharedMem",$sid,{ expires_in => 60 };
$sid = $Session{'_session_id'}; # Store the sessionid for next loop run
for (1..10) {
$X = $Session{$_}; # Read from the session
$Session{$_} = $_; # Write to the session
}
untie %Session; # Close the session
}
}
print $t - time; # time needed for this run
Perl has powerful benchmarking modules, but “time” is sometimes easier to use. The test will run 1000 times, each run creates a new session (because $sid is undef), save the session id, read some (not existing) values from the session, write some values into the session and close the session. Next the same session is opened again (inner loop run #2) and the same read/write actions are performed – because a session usually exists and I didn’t want to mix up results if the creation of a new session has some delay.
The test started – and nothing happend. After reducing the outer loop to 10, the test took 7,95 seconds to run (on the busy server running the application)! That is nearly 0,8 seconds per request for having a session – way too much.
I changed the test script to use Apache::Session::File – and it ran 0,02 seconds on the same machine. Switching back to 1000 loops made the test taking 1,63 seconds which is about 2 ms per request.
I like to use the Linux shared memory path /dev/shm for files which aren’t required after a reboot, so I tried to place the session data there – and got 1,44 seconds. I don’t think that these 0,19 ms per request really make any difference and I try not to waste any memory – but the sessions of this application will go to /dev/shm from now on.
Switching was easy:
- Add a mkdir for the session cache directory to my mod_perl startup file which is also preloading the modules
- Change the “use” (startup and session module) and “tie” (session module only) lines from Apache::Session::SharedMem to Apache::Session::File
- Add a “Directory => ‘/dev/shm/session_cache’” to the tie’s options hash
My ajax page is much faster now – and all other functions and scripts, too.

and 
and
and
and