Typographic headlines with PHP (Part 2)

Yesterday, I started a small tutorial on how to implement typographic headlines with PHP. There were some aspects to be aware of, but in general it was an easy and straight forward process. The final result looked like this:

headline_example-8bit.png

But there was one big issue I had with my script: It was far to slow (33 requests per second) for use in a production environment. But today, I'll extend my previous script with a simple caching mechanism to make it ready for the real world.

Welcome to the Pleasuredome

Basically that's where I left yesterday:

$font_file="./FFF Tusj.ttf";
$font_size=64;
$text = "An Example";

$bb = imagettfbbox($font_size,0,$font_file,$text);

$bb_width = $bb[4]-$bb[6];
$bb_height = $bb[3]-$bb[5];

$image  =  imagecreate($bb_width, $bb_height);     

$fillcolor  =  imagecolorallocate($image, 255, 255, 255);    
$fontcolor  =  imagecolorallocate($image, 69, 138, 186);    

imagefill($image, 0, 0, $fillcolor);    

imagettftext($image, $font_size, 0, abs($bb[6]), $bb_height-$bb[3], $fontcolor, 
		$font_file, $text);

header("Content-Type: image/png");
imagepng($image);

I'll put this in a function - let's say - fancyheadline($text) and will add two lines of code at the beginning of this function and change the last lines a little bit.

The final script will look like this (changes highlighted):

function fancyheadline($text)
{
	$cache="cache/".md5($text).".png";
	if(!file_exists($cache))
	{       
		$font_file="./FFF Tusj.ttf";
		$font_size=64;

		$bb = imagettfbbox($font_size,0,$font_file,$text);

		$bb_width = $bb[4]-$bb[6];
		$bb_height = $bb[3]-$bb[5];

		$image  =  imagecreate($bb_width, $bb_height);    

		$fillcolor  =  imagecolorallocate($image, 255, 255, 255);    
		$fontcolor  =  imagecolorallocate($image, 69, 138, 186);    

		imagefill($image, 0, 0, $fillcolor);    

		imagettftext($image, $font_size, 0, abs($bb[6]), $bb_height-$bb[3],
				$fontcolor, $font_file, $text); 

		header("Content-Type: image/png");
		imagepng($image,$cache);
	}       
	return '<img src="'.$cache.'" alt="'.htmlspecialchars($text).'">';

}
echo fancyheadline("An Example");

What's happening here is that I first generate a MD5 hash of my headline string $text and check if a cache file containing this hash exists or not. If it doesn't exists, create the file containing the rendered headline image. If it exists, do nothing.

At the end of the script I return a string consisting of an IMG HTML tag which would display the cached image file. (With htmlspecialchars () I convert special characters like ", &, < and > to their corresponding HTML entities, because these chars may break the validity of HTML.)

Before I can run my script, I need to create the cache directory and give it appropriate permissions:

% mkdir cache
% chmod a+rwx cache

On a production server you probably don't want to give write permissions to everyone, but will change the ownership of the directory to www-data or whatever user my web server runs as.

Now it's time to access the script in my trusted browser:

examplewcache.jpg

This looks exactly like my original yesterday's example above, but this time the script generates the headline image "in the background" and only outputs some HTML code referring to this image:

<img src="cache/e6cf1c67e6acfa204bb784cd6b25839f.png" alt="An Example">

In other words: I reduced the use and need of PHP as much as possible.

Final words by ApacheBench

First let's check the PHP script itself:

% ab -n 1000 http://demo/headline.php
This is ApacheBench, Version 2.3
...
Document Path:          /headline.php
Document Length:        71 bytes
...
Requests per second:    1801.51 [#/sec] (mean)
...

1800 requests per second. Yes, that's what I wanted to hear. But it's easy to explain: The headline image is generated only once, upon the first request. And for all following requests the script only refers to the already generated image.

And if I benchmark the image itself:

% ab -n 1000 http://demo/cache/e6cf1c67e6acfa204bb784cd6b25839f.png
This is ApacheBench, Version 2.3
...
Document Path:          /cache/e6cf1c67e6acfa204bb784cd6b25839f.png
Document Length:        7888 bytes
...
Requests per second:    3308.09 [#/sec] (mean)
...

Of course, because it's now just static data, and I'll get the most performance possible out of my server.

I started with 33 requests per second and ended somewhere in between of 1800 and 3300 requests per second.

Moving at one million miles an hour... Welcome to the Pleasuredome!

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Kai 'Oswald' Seidler writes about his life as co-founder of Apache Friends, creator of XAMPP, and technology evangelist for web tier products at Sun Microsystems.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today