Let us suppose that we have some problem and at least two solutions for it. And what we want to achieve - is to compare effectiveness for them. How to do this? Obviously, the best answer is: do tests. And I doubt there's a better way when it comes to language-specific questions (for example "what is faster for PHP: echo 'foo', 'bar' or echo('foo'.'bar')").
Ok, now we'll assume that if we want to test some code, it's equal to test some function. Why? Because we can wrap that code to function and pass it's context (if any) as it's parameters. Thus, all we need - is to have, for example, some benchmark function which will do all stuff. Here's very simple one:
function benchmark(callable $function, $args=null, $count=1)
{
$time = microtime(1);
for($i=0; $i<$count; $i++)
{
$result = is_array($args)?
call_user_func_array($function, $args):
call_user_func_array($function);
}
return [
'total_time' => microtime(1) - $time,
'average_time' => (microtime(1) - $time)/$count,
'count' => $count
];
}
-this will fit our issue and can be used to do comparative benchmarks. Under comparative I mean that we can use function above for code X, then for code Y and, after that, we can say that code X is Z% faster/slower than code Y.
The problem
Ok, so we can easily measure time. But what about memory? Our previous assumption "if we want to test some code, it's equal to test some function" seems to be not true here. Why? Because - it's true from formal point, but if we'll hide code inside function, we'll never be able to measure memory after that. Example:
function foo($x, $y)
{
$bar = array_fill(0, $y, str_repeat('bar', $x));
//do stuff
}
function baz($n)
{
//do stuff, resulting in $x, $y
$bee = foo($x, $y);
//do other stuff
}
-and we want to test baz - i.e. how much memory it will use. By 'how much' I mean 'how much will be maximum memory usage during execution of function'. And it is obvious that we can not act like when we were measuring time of execution - because we know nothing about function outside of it - it's a black box. If fact, we even can't be sure that function will be successfully executed (imagine what will happen if somehow $x and $y inside baz will be assigned as 1E6, for example). Thus, may be it isn't a good idea to wrap our code inside function. But what if code itself contains other functions/methods call?
My approach
My current idea is to create somehow a function, which will measure memory after each input code's line. That means something like this: let we have code
$x = foo();
echo($x);
$y = bar();
-and after doing some thing, measure function will do:
$memory = memory_get_usage();
$max = 0;
$x = foo();//line 1 of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
echo($x);//second line of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
$y = bar();//third line of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
//our result is $max
-but that looks weird and also it does not answer a question - how to measure function memory usage.
Use-case
Use-case for this: in most case, complexity-theory can provide at least big-O estimation for certain code. But:
- First, code can be huge - and I want to avoid it's manual analysis as long as possible. And that is why my current idea is bad: it can be applied, yes, but it will still manual work with code. And, more, to go deeper in code's structure I will need to apply it recursively: for example, after applying it for top-level I've found that some
foo()function takes too much memory. What I will do? Yes, go to thisfoo()function, and.. repeat my analysis within it. And so on. - Second - as I've mentioned, there are some language-specific things that can be resolved only by doing tests. That is why having some automatic way like for time measurement is my goal.
Also, garbage collection is enabled. I am using PHP 5.5 (I believe this matters)
The question
How can we effectively measure memory usage of certain function? Is it achievable in PHP? May be it's possible with some simple code (like benchmark function for time measuring above)?
echo(a,b);is a parse error whileecho a,b;is not.echo('foo'.'bar')- fixed, thank you