Я изучаю C, и последние несколько дней я потратил на понимание того, как получить процессорное время данного процесса или фрагмента кода. Я использую Windows 10 x64, и у меня установлен MSYS2 с настроенными подсистемами «msys2» и «mingw64», поэтому я могу сравнить код, необходимый для этой задачи, как в Windows, так и в совместимом с POSIX система (или, по крайней мере, ее эмуляция). Кроме того, я установил Visual Studio Community 2019, чтобы увидеть, есть ли разница в производительности между ним и mingw64 с точки зрения процессорного времени для запуска простого l oop с printf ().
Это POSIX подход, который я взял из одного из комплектов CS50 Course. Для этого я использовал подсистему msys2 для компиляции:
#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>
double calculate(const struct rusage *b, const struct rusage *a);
int main(void)
{
struct rusage before, after;
getrusage(RUSAGE_SELF, &before);
// Activity to be timed
for(int i = 0; i < 100000; i++)
{
printf("%i\n", i);
}
getrusage(RUSAGE_SELF, &after);
double time = calculate(&before, &after);
printf("Time: %.2f\n", time);
}
double calculate(const struct rusage *b, const struct rusage *a)
{
if (b == NULL || a == NULL)
{
return 0.0;
}
else
{
return ((((a->ru_utime.tv_sec * 1000000 + a->ru_utime.tv_usec) -
(b->ru_utime.tv_sec * 1000000 + b->ru_utime.tv_usec)) +
((a->ru_stime.tv_sec * 1000000 + a->ru_stime.tv_usec) -
(b->ru_stime.tv_sec * 1000000 + b->ru_stime.tv_usec)))
/ 1000000.0);
}
}
И здесь используется Windows API. Я скомпилировал это, используя как подсистему mingw64 (g cc), так и Visual Studio:
#Include <stdio.h>
#include <windows.h>
int GetProcessCPUTime(HANDLE hProcess, double* cpu_time);
int main(void)
{
double before;
if (GetProcessCPUTime(GetCurrentProcess(), &before) == 0)
{
return 1;
}
// Activity to be timed
for (int i = 0; i < 100000; i++)
{
printf("%i\n", i);
}
double after;
if (GetProcessCPUTime(GetCurrentProcess(), &after) == 0)
{
return 1;
}
double total = after - before;
printf("Time: %.2f\n", total);
}
int GetProcessCPUTime(HANDLE hProcess, double* cpu_time)
{
FILETIME creation, exit, kernel, user;
if (GetProcessTimes(hProcess, &creation, &exit, &kernel, &user) == 0)
{
return 0;
}
ULARGE_INTEGER kernel_t;
ULARGE_INTEGER user_t;
kernel_t.LowPart = kernel.dwLowDateTime;
kernel_t.HighPart = kernel.dwHighDateTime;
user_t.LowPart = user.dwLowDateTime;
user_t.HighPart = user.dwHighDateTime;
*cpu_time = (kernel_t.QuadPart + user_t.QuadPart) / 10000000.0;
return 1;
}
Моя гипотеза заключалась в том, что подход POSIX будет работать медленнее, потому что он должен использовать msys-2.0.dll, и и mingw64, и MSV C будут быстрее и с аналогичными результатами. Но это было не так. Результаты были (в среднем): msys2 3s mingw64 8s Visual Studio 1s
Я удивлен. Почему mingw64 такой медленный? Разве он не использует библиотеку времени выполнения Windows C? Является ли мой подход с использованием Windows API эквивалентом функции POSIX getrusage ()? Если это актуально, я использовал cmd для запуска всех трех исполняемых файлов.
Спасибо!