Your privacy is important to us! Our website uses cookies, for which we need your consent. Please review here our personal data handling and cookie policy.
|
||||||||
|
web3tracer PHP profiler automatically produces memory profiling data. To avoid problems with negative memory deltas, there are 4 indicators for memory usage:
To visualize the memory profiling data generated by the PHP profiler, use the event type dropdown on the top toolbar of KCachegrind. You can see below how the maximum allocated memory graph looks for the recursion test script:
The following graph is KCachegrind's representation of the m_all (Memory Allocated) indicator:
While also looking at the source code, you might notice something surprising: although the contents of the 3MB string that is stored in memory are generated by str_repeat and so you might expect this function is also generating the top memory usage for the script, it's not.
It is no error, however. the reason is that the 3MB string is actually allocated by the concatenation operation in function b(), and the str_repeat() is always using the same memory space for its output, because its output is always deallocated after the said concatenation operation.
This is also the reason why the script's top memory is 4MB for producing a 3MB string: a concatenation operation takes as much memory as the length of the initial string plus twice the increment. A most interesting find.
Going further with this example, if we go to the "Allocated memory" pofile, which will look something like this:
We will find that b() has no exclusive (internal) memory allocation. How can this be, that it adds to the maximum allocated memory, but it allocates nothing? Seems to make no sense. And you're right, it doesn't. But that is just because there is no way to hook into php's actual allocation functions, but rather the allocated memory is computed as a delta between the initial and final memory usage. So what happens is this: b() allocates 1MB extra each time for the concatenation (see above paragraph), but then it frees the str_repeat() result, worth the same 1MB. Although there has been actually a 1MB allocation made, there is no way for the PHP profiler to trace it and the memory allocated is reported at 0. This is a limitation of PHP that is not likely we'll overcome in the near future.
Let's go a bit further with the analysis and look at the timing for function b():
We will notice that it has an internal 19 ms (unmistakably attributed to the concatenation), but the str_repeat function only takes 5ms. How does repetitive concatenation take 4 times as much time as generating it off the bat with str_repeat? There is a logical answer here as well.
The answer is I've lied to you before, to simplify things. What actually happens when the string to be incremented is X MB long is this: PHP allocates X+1 MB for the result of the concatenation, then it copies both the initial variable and the increment in this space. that is X+1 MB read, X+1 MB write. Then it frees the X+1 MB of the old contents and the increment. It amounts to this: over the course of a 3MB iteration, str_repeat writes 3MB of memory, while the concatenation operation in b() reads 6MB and writes 6MB, totalling 12M of memory operations! Which is roughly the 4x timing disparity we noticed. This is also the longer explanation for why we add allocated and freed memory in the "Memory operations" indicator, which is not as helpful as it should be in this case; this indicator remains 0 because of the limitation mentioned above.
From a few simple graphs, we can reveal much of the inner workings of our scripts' memory management. It's a handy thing to know that memory is not just a limited resource, but that also memory and time are bound together in intricate ways. And I will not mention in this article the complexities of the garbage collector, circular references and how much time a simple unset() may take. Memory profiling is a much more complex discipline than time profiling, and we hope web3tracer, although not perfect in this regard, can help to shed some light into your most complex scripts. This PHP profiler is a tool to have when your memory is playing tricks on you.
Good luck profiling! |