How can I measure CPU time in C++ on windows and include calls of system()?
Asked Answered
M

7

7

I want to run some benchmarks on a C++ algorithm and want to get the CPU time it takes, depending on inputs. I use Visual Studio 2012 on Windows 7. I already discovered one way to calculate the CPU time in Windows: How can I measure CPU time and wall clock time on both Linux/Windows?

However, I use the system() command in my algorithm, which is not measured that way. So, how can I measure CPU time and include the times of my script calls via system()?

I should add a small example. This is my get_cpu_time-function (From the link described above):

double get_cpu_time(){
    FILETIME a,b,c,d;
    if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0){
        //  Returns total user time.
        //  Can be tweaked to include kernel times as well.
        return
            (double)(d.dwLowDateTime |
            ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001;
    }else{
        //  Handle error
        return 0;
    }
}

That works fine so far, and when I made a program, that sorts some array (or does some other stuff that takes some time), it works fine. However, when I use the system()-command like in this case, it doesn't:

int main( int argc, const char* argv[] )
{
    double start = get_cpu_time();
    double end;
    system("Bla.exe");
    end = get_cpu_time();

    printf("Everything took %f seconds of CPU time", end - start);

    std::cin.get();

}

The execution of the given exe-file is measured in the same way and takes about 5 seconds. When I run it via system(), the whole thing takes a CPU time of 0 seconds, which obviously does not include the execution of the exe-file.

One possibility would be to get a HANDLE on the system call, is that possible somehow?

Micrococcus answered 14/11, 2013 at 11:49 Comment(0)
F
0

Linux:

Furness answered 14/11, 2013 at 11:56 Comment(1)
As for CPU time on windows, you might be able to use GetProcessInformation() , but it requires a HANDLE to the childs, which you do not get with system() - the other means seems to be finding and reading the proper perfomance counters, which is non-trivial, and I don't know enough about it to answer that part.Furness
E
0

It will actually prints the CPU time that your program takes. But if you use threads in your program, It will not work properly. You should wait for thread to finish it's job before taking the finish CPU time. So basically you should write this:

WaitForSingleObject(threadhandle, INFINITE);

If you dont know what exactly you use in your program (if it's multithreaded or not..) you can create a thread for doing that job and wait for termination of thread and measure the time.

DWORD WINAPI MyThreadFunction( LPVOID lpParam );
int main()
{
DWORD   dwThreadId;
HANDLE  hThread;

int startcputime, endcputime, wcts, wcte;

startcputime = cputime();

hThread = CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            MyThreadFunction,       // thread function name
            NULL,                   // argument to thread function 
            0,                      // use default creation flags 
            dwThreadIdArray);

WaitForSingleObject(hThread, INFINITE);

endcputime = cputime();

std::cout << "it took " << endcputime - startcputime << " s of CPU to execute this\n";

return 0;
}

DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{ 
    //do your job here
    return 0; 
} 
Ellon answered 14/11, 2013 at 12:4 Comment(0)
K
0

If your using C++11 (or have access to it) std::chrono has all of the functions you need to calculate how long a program has run.

Khalid answered 4/2, 2015 at 2:34 Comment(1)
But it only returns time used by the calling process, and the topic of the question is measurement of child processes.Wellestablished
W
0

You'll need to add your process to a Job object before creating any child processes. Child processes will then automatically run in the same job, and the information you want can be found in the TotalUserTime and TotalKernelTime members of the JOBOBJECT_BASIC_ACCOUNTING_INFORMATION structure, available through the QueryInformationJobObject function.

Further information:

Beginning with Windows 8, nested jobs are supported, so you can use this method even if some of the programs already rely on job objects.

Wellestablished answered 28/4, 2015 at 18:43 Comment(0)
R
0

I don't think there is a cross platform mechanism. Using CreateProcess to launch the application, with a WaitForSingleObject for the application to finish, would allow you to get direct descendants times. After that you would need job objects for complete accounting (if you needed to time grandchildren)

Revet answered 26/7, 2015 at 9:0 Comment(0)
B
0

You might also give external sampling profilers a shot. I've used the freebie "Sleepy" [http://sleepy.sourceforge.net/]and even better "Very Sleepy" [http://www.codersnotes.com/sleepy/] profilers under Windows and been very happy with the results -- nicely formatted info in a few minutes with virtually no effort.

There is a similar project called "Shiny" [http://sourceforge.net/projects/shinyprofiler/] that is supposed to work on both Windows and *nix.

Barbirolli answered 8/10, 2015 at 6:19 Comment(0)
K
-1

You can try using boost timer. It is cross-platform capable. Sample code from boost web-site:

#include <boost/timer/timer.hpp>
#include <cmath>

int main() {
 boost::timer::auto_cpu_timer t;

  for (long i = 0; i < 100000000; ++i)
    std::sqrt(123.456L); // burn some time

 return 0;
}
Kura answered 24/11, 2013 at 7:30 Comment(1)
But it only returns time used by the calling process, and the topic of the question is measurement of child processes.Wellestablished

© 2022 - 2024 — McMap. All rights reserved.