Benchmark: APC vs. MySQL MEMORY fetching Speed
I once wrote a article about APC and MySQL MEMORY table caching and found out that APC needs very much memory compared to MySQL MEMORY. Now i did a short benchmark to check out the fetching speed of these two solutions with a interesting result.
Script
First, the benchmark script:
// Simple test script benchmarking cache access times
// of APC and MySQL MEMORY
// by: Julius Beckmann (juliusbeckmann.de)
// Config
$n = 10000;
$newline = "<br/>\n";
// Init benchmark array with $n entrys
$array = array();
$i = 0;
while($i++ < $n) {
$array[] = rand(0,999999);
}
echo "Testarray has ".count($array)." random integer entrys".$newline;
// Check direct array access time
$time_start = microtime(true);
$i = 0;
while($i < $n) {
$devnull = $array[$i++];
}
$time_end = microtime(true);
$time = $time_end-$time_start;
echo number_format($time, 3, '.', '')
." seconds - direct array access".$newline;
// Adding these array values to APC
foreach($array as $k => $v) {
apc_store('test_'.$k, $v);
}
// Benchmarking apc_fetch
$time_start = microtime(true);
$i = 0;
$count = count($array);
while($i < $count) {
$devnull = apc_fetch('test_'.$i++);
}
$time_end = microtime(true);
$time = $time_end-$time_start;
echo number_format($time, 3, '.', '')
." seconds - apc_fetch()".$newline;
// Deleting APC entrys
foreach($array as $k => $v) {
apc_delete('test_'.$k);
}
// Benchmark mysql
// Connect
$link = mysql_connect('localhost', 'username', 'password');
if (!$link) die('Not connected : ' . mysql_error());
$db_selected = mysql_select_db('database', $link);
if (!$db_selected) die ('Can\'t use foo : ' . mysql_error());
// Adding these array values to mySQL Memory table
/* TABLE:
CREATE TABLE `test_memory` (
`key` INT UNSIGNED NOT NULL ,
`value` INT UNSIGNED NOT NULL
) ENGINE = MEMORY
*/
foreach($array as $k => $v) {
mysql_query('INSERT INTO test_memory (`key`,`value`) VALUES ('.$k.', '.$v.');');
}
// Benchmark mysql memory table
$time_start = microtime(true);
$i = 0;
$count = count($array);
while($i < $count) {
list(,$devnull) = mysql_fetch_row(mysql_query('SELECT * FROM `test_memory` WHERE `key` ='.$i++.';'));
}
$time_end = microtime(true);
$time = $time_end-$time_start;
echo number_format($time, 3, '.', '')
." seconds - mysql_query from MEMORY table FIRST RUN".$newline;
// Benchmark a second time to check for mysql caches
$time_start = microtime(true);
$i = 0;
$count = count($array);
while($i < $count) {
list(,$devnull) = mysql_fetch_row(mysql_query('SELECT * FROM `test_memory` WHERE `key` ='.$i++.';'));
}
$time_end = microtime(true);
$time = $time_end-$time_start;
echo number_format($time, 3, '.', '')
." seconds - mysql_query from MEMORY table SECOND RUN".$newline;
// Trunc memory table
mysql_query('TRUNCATE TABLE test_memory;');
?>
Result
Output of the script:
0.002 seconds - direct array access
0.011 seconds - apc_fetch()
1.304 seconds - mysql_query from MEMORY table FIRST RUN
1.167 seconds - mysql_query from MEMORY table SECOND RUN
The measured times are only fetching times. Fetching should by done much often in reality than storing, so it is way more important.
As you can see the direct access is the fastes. APC is ony 5 times slower than direct access. That is very fast compared to the MySQL equivalent. MySQL took about 100 times longer than APC. This result is astonishing. I though MySQL might be about 5 or 10 times slower then APC, but 100 is very much.
I also let the MySQL select run twice to check for buffers that might come in but no better result.
A "stangl" already mentioned, the overhead produced by MySQL for querying, parsing, and returning is very big and slow compared to APC.
Conclusion
If you need only very few variables to store, try APC first. MEMORY TABLES might be handy when you need to save more than APC can handle effictively.
If anybody can find a mistake i did, please let me know. Maybe MEMORY tables are not that slow as my benchmark turned out.
Interessant wäre noch ein Vergleich der Parallelität. Die ist wichtig, um den meist relevanteren Durchsatz für eine konkrete Anwendung zu bestimmen. Auf modernen Architekturen sollte man immer mit vielen Threads testen, wenn man nicht gerade im Realtime-Bereich arbeitet. Und da bist du mit PHP ganz sicher nicht. ;-)
Wenn du auf Performance stehst, schau' dir mal eine garbage collected Sprache an. Und zwar mit Garbage Collection aus, also Reset der Applikation, wenn kein Speicher mehr da ist.
Very good post, seems that APC is very fast compared to MYSQL memory!
Adding a primary key to your table would improve your mySQL performance. The database will still be far slower than APC, but has other advantages than can be used in a real life application (complex joins with other tables, ...)
Thanks for the benchmark anyway!