Skip to content

Instantly share code, notes, and snippets.

@wareya
Created January 27, 2025 02:34
Show Gist options
  • Save wareya/52ac59709af286b9a5d55f8d76ebdb20 to your computer and use it in GitHub Desktop.
Save wareya/52ac59709af286b9a5d55f8d76ebdb20 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <chrono>
using namespace std;
#ifndef _WIN32
#define redir_str " >/dev/null 2>/dev/null"
#include <sys/times.h>
#include <unistd.h>
double get_cpu_time()
{
struct tms my_time;
clock_t my_clock = times(&my_time);
(void)my_clock;
double utime = (double)my_time.tms_cutime / sysconf(_SC_CLK_TCK);
double stime = (double)my_time.tms_cstime / sysconf(_SC_CLK_TCK);
auto ret = utime;
ret += stime;
return ret;
}
void system_prepare();
#else
#define redir_str ""
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <windows.h>
double _time = 0.0;
double get_cpu_time() { return _time; }
HANDLE subproc_id = 0;
int system(char * cmd)
{
STARTUPINFO sinfo = {};
sinfo.cb = sizeof(STARTUPINFO);
sinfo.dwFlags = STARTF_USESTDHANDLES;
HANDLE hNul = CreateFile("NUL", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
sinfo.hStdOutput = hNul;
sinfo.hStdError = hNul;
PROCESS_INFORMATION pinfo = {};
if (!CreateProcess(0, cmd, 0, 0, 0, 0, 0, 0, &sinfo, &pinfo))
return -1;
WaitForSingleObject(pinfo.hProcess, INFINITE);
FILETIME ctime, xtime, stime, utime;
GetProcessTimes(pinfo.hProcess, &ctime, &xtime, &stime, &utime);
ULARGE_INTEGER stime_u, utime_u;
stime_u.LowPart = stime.dwLowDateTime;
stime_u.HighPart = stime.dwHighDateTime;
utime_u.LowPart = utime.dwLowDateTime;
utime_u.HighPart = utime.dwHighDateTime;
// Convert to milliseconds
double stime_s = stime_u.QuadPart / 10000000.0;
double utime_s = utime_u.QuadPart / 10000000.0;
_time += utime_s;
_time += stime_s;
DWORD ret;
GetExitCodeProcess(pinfo.hProcess, &ret);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
return ret;
}
#endif
static inline double get_time()
{
auto now = std::chrono::steady_clock::now();
auto duration = now.time_since_epoch();
double ret = std::chrono::duration<double>(duration).count();
return ret;
}
int main(int argc, char ** argv)
{
if (argc == 1)
return puts("usage: benchify \"cmd1\" \"cmd2\" ...");
vector<string> cmds;
vector<vector<double>> times;
vector<vector<double>> times2;
for (size_t i = 1; i < (unsigned)argc; i++)
{
cmds.push_back(argv[i]);
times.push_back({});
}
for (size_t i = 0; i < cmds.size(); i++)
{
printf("command %zd/%zd: %s...\n", i+1, cmds.size(), cmds[i].data());
double t = 0.0;
double t2 = 0.0;
for (size_t j = 0; j < 10; j++)
{
double start = get_time();
double ustart = get_cpu_time();
auto ret = system((cmds[i] + redir_str).data());
double uend = get_cpu_time();
double end = get_time();
if (ret)
{
printf("subcommand failed: %s\n", cmds[i].data());
exit(ret);
}
times[i].push_back(end - start);
t += times[i].back();
t2 += uend-ustart;
//printf("\r...%f ", times[i].back());
printf("\r...%9.4f (cpu: %9.4f) (%zd/%d)", t/(j+1), uend-ustart, j+1, 10);
fflush(stdout);
}
t /= 10.0;
t2 /= 10.0;
printf("\r %9.4f (cpu: %9.4f) (%d/%d)\n", t, t2, 10, 10);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment