4

How can I calculate the CPU time actually used by my php script?

Note this is NOT what I'm looking for:

<?php
$begin_time=microtime(true);
//..
//end of the script:
$total_time=microtime(true)-$begin_time;

because that would give me the time elapsed. That may include a lot of time used by unrelated processes running at the same time, as well as time spent waiting for i/o.

I've seen there is getrusage(), but a user comment in the documentation page says:

getrusage() reports kernel counters that are updated only once application loses context and a switch to kernel space happens. For example on modern Linux server kernels that would mean that getrusage() calls would return information rounded at 10ms, desktop kernels - at 1ms.

getrusage() isn't usable for micro-measurements at all - and getmicrotime(true) might be much more valuable resource.

so that doesn't seem to be an option, is it?

What alternatives do I have?

matteo
  • 2,934
  • 7
  • 44
  • 59
  • It says that getmicrotime(true) might be a much more valuable resource, doesn't that mean you are encouraged to use it? – Jonast92 Apr 15 '13 at 19:18
  • 2
    Oh and by the way, could this not help you? http://stackoverflow.com/questions/8413323/cpu-get-usage-in-php Look at the accepted answer – Jonast92 Apr 15 '13 at 19:20
  • @Jonast92 regarding your first comment, it says microtime(true) is much more valuable *compared to getrusage*, and it also says getrusage is completely useless. microtime just doesn't measure what I need to measure. – matteo Apr 16 '13 at 01:00
  • @Jonast92 regarding the linked question, the answer relies on getrusage, if getrusage is unreliable (and btw I have verified it is completely), then that cannot be reliable – matteo Apr 16 '13 at 01:01

2 Answers2

1

Define "your" I/O. Technically a move of memory to cpu registers is I/O. Are you saying you want to remove that time from your calculation? (I'm guessing no)

What I'm getting at is you are looking to profile your code in some way most likely. If you want to measure time not spent reading/writing to files or network sockets, just use microtime and put extra calls around portions doing I/O. Then you will also get an idea of how much time your I/O is taking. More likely you will find you have some loop taking more time than you expect.

When I profile like this I either use profiling tools in eclipse, or I use a time logger and do some kind of binary search-ish insertion of the time logging into the code. Usually I find some small area of code that is taking 85% of the measured time and do optimization there.

Also as a side note, don't let the perfect become the enemy of the practical. 90% of the time during your process your calls won't be interrupted by some other process and your microtime counts will be close enough.

Zak
  • 24,947
  • 11
  • 38
  • 68
  • I already defined what I meant by i/o when I said "waiting for i/o" so I was talking about those forms of i/o where the process waits. Your proposed trick of using microtime and putting extra calls around i/o and network operations will not solve the other problem: avoiding to count time that is not spent by the process at all but by other processes. – matteo Apr 16 '13 at 00:49
  • having profiled hundreds of thousands of lines of php code I have never run across a case I couldn't profile simply using microtime to isolate the long running portion. I'm just saying... you might have a .00001% case, but I doubt it. – Zak Apr 16 '13 at 00:53
  • Regarding this: "90% of the time during your process your calls won't be interrupted by some other process and your microtime counts will be close enough." - no way. Do a few dozens requests at the same time to a web server and watch dozens of httpd processes all running at the same time consuming 1% cpu. Oh, ok, they probably don't get interrupted randomly in the middle of non-io code but only when waiting for i/o? so ok, your trick might 90%-work, but hey, surrounding each and every query and file read with profiling calls isn't exactly "practical". – matteo Apr 16 '13 at 00:55
  • Also I'm not (only) trying to "isolate the long running portion", I'm trying to measure how much of the time the php script takes to run (from beginning to end) is actually being spent in PHP, and how much is not; because I've already subtracted all the time spent in queries, and I don't have much (almost any) file i/o, and yet i get very uneven running time where the very same request (producing identical response) can take anywhere from x to 5x time, so i definitely need to check whether the time is being spent in php or not. – matteo Apr 16 '13 at 01:34
0

You can use getrusage()

Full example:

<?php

function rutime($ru, $rus, $index){
    return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000))
     -  ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000));
}

$cpu_before = getrusage();
$ms = microtime(true) * 1000;

sleep(3);
$tab = [];
for($i = 0; $i < 500000; $i++) {
  $tab[] = $i;
}

$cpu_after = getrusage();
echo "Took ".rutime($cpu_after, $cpu_before, "utime")." ms CPU usage" . PHP_EOL;
echo "Took ".((microtime(true) * 1000) - $ms)." ms total". PHP_EOL;

Source: https://helpdesk.nodehost.ca/en/article/how-to-calculate-real-cpu-usage-in-a-php-script-o3ceu8/

  • The comments on the original question state clearly the asker is aware of `getrusage` and due to its limitations it is not what they're looking for. – Martin May 12 '20 at 18:46
  • Yes, you're right, but I will leave this answer for other people because this example might be useful when somebody will want to benchmark PHP performance in mathematical operations (integrals, numerical methods etc.). – SnakeMaster May 12 '20 at 18:57