Storing Websites in Memory Using PHP
Page last updated on 2011 / 04 / 09With the proliferation of large one-size-fits-all content management systems such as Wordpress and Drupal, people with minimal technical skills can get a site online. The downside of using these popular systems (aside from security) is that they often suffer from code-bloat, and thus don't work as fast as they should. Nine times out of ten, the people using these CMS's (as apparent from the front end of their website) are simply using a template to hold their content. Speed is always an attractive quality of any website, making your site quicker gives it a better rep.
Operating Systems are good at caching regularly accessed files on disk. A file based content management system will typically be quick when all the regularly used files it accesses are in the disk cache. For all other requests out of the disk cache, a disk seek is required, which is many, many times slower than using a cache or memory. See this short conversation about disk seeks and why they are the bottleneck in today's computer world. Apparently, 'disks are the new tape'.:
With that in hand, how about making a site that is really fast and really simple, and is as fast (or very close) to your hardware limits? Loading a page of static content should be very quick, regardless of what system is used to generate the content. The following is an example of storing a small website in memory, rather than on disk
PHP has a range of memory functions that allows you to store data permanently in memory. This means you can store the information for all users visiting a web page and even for applications other than PHP to use.
So how can memory be used? There are a number of ways to use memory to your advantage.
Storing HTML Templates in Memory
If you are a user of MySQL, you may be aware that MySQL also takes advantage of memory by using the key_buffer and innodb_buffer_pool variables to determine a size of memory to store indexes. This allows for faster retrieval and again, avoids disk seeks. This is apparent when you run a similar slow queries, after the first time the frequently accessed index values are in memory and don't have to be retrieved from disk. If you are fortunate enough to have a large value for key_buffer or innodb_buffer_pool, you can fit all your indexes (and data) of a database in memory.
If you have this luxury, your site may already be fast, but you could also load your templates from memory too! You can download this example which contains the following script and a folder containing 3 simple templates.
You can call the script to access a template by loading up script.php?a=$num, where $num is the number of the template you want.
<?php isset($_GET['a']) && ctype_digit($_GET['a']) or die('Invalid page'); @$id = shmop_open(ftok(__FILE__,'r'),"a",0666,0); // See if memory is already created, suppress error messages if(empty($id)) { $templates = array_slice(scandir('templates'),2); // List of templates to use $offset = 8 + (count($templates) * 4); // 4 bytes to store template count, 4b for memory size, 4b for each template offset $offsets = $offsets2 = array(); foreach($templates as $template) { $offsets[$template] = $offset; // Storing template filename and where it will go in shared memory $offsets2[] = pack('N',$offset); // Binary form of offset (4 bytes) $offset += filesize('templates/'.$template); // Increment offset by filesize } $offsets2[] = pack('N',$offset); // Add final value to indicate size of memory and the end of the last template $id = shmop_open(ftok(__FILE__,'r'),"c",0666,$offset); // Open shared memory shmop_write($id,pack('N',count($templates)).implode('',$offsets2),0); // Write offset data to memory foreach($offsets as $template => $offset) shmop_write($id,file_get_contents('templates/'.$template),$offset); // Write actual template HTML to memory } $tcount = array_shift(unpack('N',shmop_read($id,0,4))); // Get count of templates stored in memory if($_GET['a'] > $tcount) die('No such template exists'); $offsets = unpack('N2',shmop_read($id,$_GET['a'] * 4,8)); // Get beginning and end pointers for template echo vsprintf(shmop_read($id,$offsets[1],$offsets[2] - $offsets[1]),array('My Title','My Description','','My Header','<p>My Content</p>')); // Read template from memory and output with unique page variables shmop_close($id); ?>
Tweet