The Blueprint
Benchmarking code is one of those often talked about things that most new to intermediate programmers have probably heard about, but don’t know how to actually do it. Even a quick Google search on it will give you all sorts of mis-information and very labor intensive ways to find where your code is slowing down.
Is Microtime() Bad?
Many of the “common” ways involve using the microtime() function to mark a start and end time and then doing some math to see how long it took to get from A to B. On the surface there is nothing wrong with this. In fact, we use this same method to output overall script generation times or SQL processing times to get a feel for when we write an extremely inefficient piece of code or SQL statement. A sort of alarm beacon to say “Hey, this code is WAY to slow”.
If you ask most race car drivers/owners that win consistently, they will always tell you that their success is in the details. It’s not the big things, it’s the 20 small tweaks that put them out in front their competition. And if you are developing a full blown CMS or web application and relying solely on microtime(), then you are sorely missing out on some tools you can use to take your code from bearable to fast.
Moving Beyond Microtime()
So, we obviously use microtime() to immediately see how our SQL calls and overall code is performing. If there is a slowdown ,then how do you figure out where it’s happening? Do you go through each file and add in these microtime()’s before and after each set of code? No.. that would be way to labor intensive (even though I have done it a time or two). Our answer is to use the amazing PHP extension xDebug . A few years ago we installed it as a way to trace through errors more effectively. It will overwrite PHP’s native error’s and output a stack/function trace to see how you got the error, which is extremely useful.
Another useful part of xDebug is it’s built in PHP Profiler, which is what we will use to find the slowdowns. If you turn it on, it generates a cachegrind file that can be analyzed by one of the many programs out there. We use a web based analyzer called WebGrind, which is basically just a set of PHP scripts that go through the files that xDebug generates. It will show you EVERY function that was called, how many times it was called and how long it took to run. It also shows you what files were included and how long each of those took to process. It is an amazing tool that will give you quick results on your entire code. Just this past week I reviewed a page and realized that I left some debugging code in that was eating up some serious memory.
Load Up The Server
Another tool we use is Siege, which allows the us hit a web server with a number of concurrent simulated users. Basically we stress test the code and see how fast it will respond. We set some max response time numbers that we will stay below. This helps us avoid adding too many features on one page, making it slow. Siege is a command line tool that I’ve only ever installed on a Mac (linux) but it does say it will install on Windows. To ease the installation I also use a program for Mac called DarwinPorts, but doing a regular install is not that big of a deal.
Some output from Siege.
% siege -c 5 http://akira.localhost -t30s Transactions: 1406 hits Availability: 100.00 % Elapsed time: 30.47 secs Data transferred: 14.54 MB Response time: 0.08 secs Transaction rate: 55.14 trans/sec Throughput: 0.48 MB/sec Concurrency: 4.99 Successful transactions: 1406 Failed transactions: 0 Longest transaction: 20.61 Shortest transaction: 0.02
In this example we hit the server with 5 users for 30 seconds and the output will show us how the code performs. The 2 main numbers we look at is Response Time and Transaction Rate. As you add features and more code it will effect these numbers, especially response time since that is the measure of how long it takes to send the first bits of data. If we can optimize our code to come in under our max response time, then that give us room to add more features without worrying about the app feeling sluggish.
Is It Overkill
Maybe. If you’re throwing together some quick scripts, then who cares? But if you are developing a full application that you want people to use then you might begin to care. We can not be lazy developers. Loading in a bunch of overhead to speed up development at the expense of our users is lazy coding. The only way to determine if we went too far in feature bloat on a page or using to much overhead is to benchmark and review our code. Anyone can read the PHP manual and create a website, but to be a great programmer you have to know where you are writing bad code and work to improve it.
When diving into PHP frameworks one of the handiest set of functions/methods you will find are the “Helpers“. The reason I like them so much is because they can really shorten the time it takes to write your code. A quick call to a helper can output lines and lines of HTML without actually writing it.
Doing more and more CSS/XHTML development brought to light that sometimes there might be a need to wrap an image with a span or div element to produce a dropshadow effect or to position it how you want. Chris and I were having a discussion about this and he came up with an idea of adding some Javascript “helpers” to speed up the coding of our CSS/XHTML.
Let me give you an example to help clarify what I’m talking about. Let’s say we have an image and we need that image to have a dropshadow. To do this we need to wrap it in a span tag so that our CSS works properly. So everywhere we want a dropshadowed image we would have to have something like this:
<span><img src = "image.png" /></span>
But we could easily write a javascript function (in our case we use jQuery) to have it auto-wrap all img elements having the class “dropshadow” with span tags.
$('img.dropshadow').wrap("<span></span>");
This simplifies and speeds up the HTML we have to write, because all we have to put into our templates is an img tag. In this case it doesn’t save a ton of time, but when you think about it in terms of styling forms with images or changing buttons to use different image types or styles you really begin to save a lot of time. And the best part is that you can keep things semantically correct. The markup doesn’t need span tags to keep the semantic meaning of having an image. The spans are there just to add the detail of the dropshadow in.
I’ve seem this methodology used in many plugins, so we’re not coming up with any revolutionary. But the point of this post is to try to push developers that have the convenience of using javascript, to use it to speed up their development. In an upcoming post we’re going to be sharing our use of a helper that simplifies how we style many different buttons in Mosaic. Hopefully that will show a real world example where it is literally saving us hours of work, over the course of building the app, everywhere we have need of a button.
PHP 5.2 brought us native use of a DateTime object for handling dates and times instead of using procedural date(), time() and strtotime() type functions. Among other things, this really helps us move away from thinking of dates and times in seconds (via a unix timestamp) and as such, having to save an integer in a database and/or using arithmetic (# of seconds X 60 = minutes, etc..) to manipulate dates.
So now that we can think of dates and times as a true date (e.g. 2009/04/27) all the way from PHP to MySQL, using a true date/time column type, it really speeds thing up. However, in the native DateTime class constants there is not a MySQL format for inserting the date object directly into a database. I realized that all I needed to do was create my own constant that aligns with the prebuilt ones.
Here is the only code you need
define('DATE_MYSQL', "Y/m/d H:i:s");
Here it is in context.
define('DATE_MYSQL', "Y/m/d H:i:s");
$dateTime = new DateTime("now");
echo $dateTime->format(DATE_MYSQL);
You’ll notice I use the same format as the other date constants like DATE_RSS to be consistent. Also note that with this same code you can set up any type of format that you can use on your site or in your code.
Search The Blog
Categories
Archives
- June 2009
- May 2009
- April 2009
- February 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- April 2008
- March 2008
- February 2008
- July 2007
