Lately i’ve been working on a lot of things that require me to “benchmark” the time it takes for parts of my code to run. This means that I have been using microtime() a lot!
So rather than waste time rewriting the same code over and over again I decided to write an “AppTimer” class to make things a little simpler!
More importantly, I’m going to let you have it for free, and you don’t even have to give me your email address! 😛
Here’s the project repo on GitHub: AppTimer on GitHub
I’ve created a few examples so you can see how to use it. 🙂
BasicExample.php
The most basic way to use the AppTimer class is to create a $Timer object and then call the AppTimer Start() method. Then you just run your code or call your function.
Once your code is is done executing use the AppTimer Stop() method.
The AppTimer Report() method will return a human readable string with how long it took your code to run.
You can explicitly destroy the AppTimer object after using it if you are working in a memory constrained environment as demonstrated below.
<?php include('AppTimer.Class.php'); // Include AppTimer class file $Timer = new AppTimer(); // Create Timer $Timer->Start(); // Start() Timer // Code you want to time $Timer->Stop(); // Stop() Timer echo $Timer->Report() . PHP_EOL; // Report() // Destroy $Timer Object $Timer = NULL; // Reclaim memory immediately by overwriting NULL on Timer object's memory space unset($Timer); // Let Garbage Collection know it can eat the variable ?>
The result of this code should look something like this:
0.0001 Seconds
AutoStartAndReportExample.php
I included a few “features” in the AppTimer to make it more useful. The first being ‘Auto Start’ which means that the Timer will start automatically as soon as it is created in memory rather than requiring you to use the AppTimer Start() method.
The way to use Auto Start is to pass a 1 or true boolean value to the class constructor as I demonstrate below.
Additionally I have implemented an ‘Auto Report’ feature on the AppTimer Stop() method which will automatically call the AppTimer Report() method for you when you pass a 1 or true boolean value to the Stop method, which I also demonstrate below.
Further, the AppTimer Report() method can be used before you call the AppTimer Stop() method to get an immediate report of the elapsed time.
<?php include('AppTimer.Class.php'); // Include AppTimer class file // Use true or 1 to Auto Start the Timer when the object is instantiated $Timer = new AppTimer(1); usleep(1000000); // wait for 1 seconds echo $Timer->Report() . PHP_EOL; // Use Report() before Timer is stopped to get elapsed time usleep(3000000); // wait for 3 seconds echo $Timer->Stop(1) . PHP_EOL; // Use true or 1 to Auto Report echo $Timer->Report() . PHP_EOL; // Report() wont change after Stop() // Destroy $Timer Object $Timer = NULL; // Reclaim memory immediately by overwriting NULL on Timer object's memory space unset($Timer); // Let Garbage Collection know it can eat the variable
The result of this code should look something like this:
1.0002 Seconds
4.0005 Seconds
4.0005 Seconds
First you will notice that the program waited 1 second and then gave a report that 1.0002 Seconds had passed. Also notice that 4.0005 Seconds appears twice. This is because I use the Stop(1) method to stop and Auto Report how long the $Timer object was in operation.
I then called Report() method manually to show that the time wont change after the timer is stopped.
FunctionCallbackExample.php
The AppTimer class does reduce and simplify things however in the end, you will still basically end up either using Auto Start or the Start() method as well as Stop() & Report or Auto Report…
The smarter and or more experienced among my readers will probably be figuring they can wrap these methods up into their own timer function and then pass their code to the function via a callback (for my non technical readers this means to do less work & improve code quality at the same time).
The thing is you would have to implement that system every time you start a new project… it’s still better/faster, though is in no way optimal!
The A+ students in the audience are thinking to themselves… “can’t you just do it for me?”… to which my response is “Yes! Yes I can!”. 😛
In this example I have implemented a function called ExampleCountFunction() which has two arguments ($count_to & $message) and if no arguments are passed both variables have default values.
First, instantiate a $Timer object then use the AppTimer CallbackTimer() method as I show below to call your function and time how long it takes for it to run.
Notice I don’t use Start(), Stop(), Auto Start or Report() with CallbackTimer(). It will handle everything for you and return the results of the Report() when it is done.
The first argument is the name of your function as a String data type. The second argument (which is optional) is an array of variables/arguments for your function.
In this example I demonstrate using the CallbackTimer() method with and without passing arguments to the function.
<?php include('AppTimer.Class.php'); // Include AppTimer class file // Example Function to Time function ExampleCountFunction($count_to = 1000000, $message = 'No Message Was Specified.'){ $report_at = round($count_to / 2); // iterate $i from 0 to $count_to and echo $message at 1/2 way for($i=0;$i<$count_to;$i++){ if($i == $report_at){ echo $message . PHP_EOL; } } } $Timer = new AppTimer(); // New Timer Object // No need to Start, Auto Start, or Report() with CallbackTimer() echo $Timer->CallbackTimer('ExampleCountFunction') . PHP_EOL; // No Arguments echo $Timer->CallbackTimer('ExampleCountFunction', array(6543210, 'Geek Girl Joy')) . PHP_EOL; // Has Arguments // Destroy $Timer Object $Timer = NULL; // Reclaim memory immediately by overwriting NULL on Timer object's memory space unset($Timer); // Let Garbage Collection know it can eat the variable
The result of this code should look something like this:
No Message Was Specified.
0.2561 Seconds
Geek Girl Joy
1.6415 Seconds
From these results you can see that the first time I used the CallbackTimer() method I didn’t specify any arguments so ExampleCountFunction() used it’s defaults.
The function counted to 1 Million and echoed it’s $message variable (‘No Message Was Specified’) 1/2 way through counting.
Once ExampleCountFunction() completed its task the callback timer stopped the timer and reported the duration.
I then use the same $Timer object again to run the same function ExampleCountFunction() as before but the second time I used an array in the second argument of CallbackTimer() method to pass argument values to my function.
The result is ExampleCountFunction() takes longer to run because instead of counting to 1 Million I have it counting to 6,543,210.
Additionally, the $message output is different because I included a string in the second index position of the CallbackTimer() arguments array which lines up with the second argument ExampleCountFunction($count_to, $message).
Values in the array are passed in order to the corresponding argument on your function.
ObjectMethodCallbackExample.php
Some of you Object Oriented programmers will probably not want to include my software (the AppTimer class) with your software but you may still want to use it to test your code.
The CallbackTimer() method will also work with an Object and call it’s methods for you! This means that you can just instantiate an AppTimer object along with your Object and you never need to mix my code into your Class files.
The way you do it is to use an array for the CallbackTimer() $callback variable as I demonstrate below.
The first index position of the $callback array should be the variable reference to your object. The second position should be the name of the method you want to time and of course you can pass arguments to your methods as needed by using a second arguments array as demonstrated.
<?php include('AppTimer.Class.php'); // Include AppTimer class file // Example Class Object class ExampleClassObject { // Method without args function HelloWorld() { echo 'Hello World' . PHP_EOL; } // Method with args function Add($a, $b) { if(is_numeric($a) && is_numeric($b)){ echo "Add($a, $b) = " . ($a + $b) . PHP_EOL; } } } $Timer = new AppTimer(); // New Timer Object $Example = new ExampleClassObject(); // Create instance of your object // Time an object method without args $HelloWorld_method_run_time = $Timer->CallbackTimer(array($Example, 'HelloWorld')); // Time an object method with args $Add_method_run_time = $Timer->CallbackTimer(array($Example, 'Add'), array(9, 1)); // Destroy $Timer Object $Timer = NULL; // Reclaim memory immediately by overwriting NULL on Timer object's memory space unset($Timer); // Let Garbage Collection know it can eat the variable // Echo Results echo "\$Example->HelloWord() Run Time: $HelloWorld_method_run_time" . PHP_EOL; echo "\$Example->Add(9, 1) Run Time: $Add_method_run_time" . PHP_EOL;
The result of this code should look something like this:
Hello World
Add(9, 1) = 10
$Example->HelloWord() Run Time: 0.0001 Seconds
$Example->Add(9, 1) Run Time: 0.0001 Seconds
As you can see both methods run, the first without arguments and the second with arguments.
The reports are assigned to variables.
After the $Timer object is destroyed I echo the results as interpolated strings.
GetTimeExample.php
One final feature that I would like to demonstrate separately is the AppTimer GetTime() method.
Basically what this does is let you pass the GetTime() method a number (as seconds) and get a formatted string back.
Note that GetTime() will overwrite the private $start & $stop properties of the $Timer object so you should not use GetTime() on an object that you are using to time.
<?php include('AppTimer.Class.php'); // Include AppTimer class file $Timer = new AppTimer(); // New Timer Object echo $Timer->GetTime(89003) . PHP_EOL; // pass the number of seconds // Destroy $Timer Object $Timer = NULL; // Reclaim memory immediately by overwriting NULL on Timer object's memory space unset($Timer); // Let Garbage Collection know it can eat the variable
The result of this code should look exactly like this:
25 Hours 43 Minutes 24 Seconds
As you can see AppTimer supports Hours, Minutes and Seconds.
I didn’t intend this class to be a full chronometer just a simple timer so I didn’t add additional conversion for Days, Weeks, Months, Years, Decades etc… In any case, we now have a tool to benchmark our PHP code! 😉
With that, I will see you all in my next post.
Much Love,
~Joy