-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathsc_benchmark.cc
More file actions
150 lines (129 loc) · 4.89 KB
/
sc_benchmark.cc
File metadata and controls
150 lines (129 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/// \file sc_benchmark.cc memory info, timers, etc for benchmarking
#include "sc_benchmark.h"
#include "sc_memmgr.h"
#ifdef _WIN32
#include <windows.h>
#include <psapi.h>
#else
#include <sys/time.h>
#include <ctime>
#include <unistd.h>
#endif
#include <assert.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <ios>
/// mem values in kb, times in ms (granularity may be higher than 1ms)
benchVals getMemAndTime( ) {
benchVals vals;
#ifdef __linux__
// adapted from http://stackoverflow.com/questions/669438/how-to-get-memory-usage-at-run-time-in-c
std::ifstream stat_stream( "/proc/self/stat", std::ios_base::in );
// dummy vars for leading entries in stat that we don't care about
std::string pid, comm, state, ppid, pgrp, session, tty_nr;
std::string tpgid, flags, minflt, cminflt, majflt, cmajflt;
std::string /*utime, stime,*/ cutime, cstime, priority, nice;
std::string O, itrealvalue, starttime;
// the fields we want
unsigned long utime, stime, vsize;
long rss;
stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
>> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
>> utime >> stime >> cutime >> cstime >> priority >> nice
>> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
long page_size_kb = sysconf( _SC_PAGE_SIZE ) / 1024; // in case x86-64 is configured to use 2MB pages
vals.physMemKB = rss * page_size_kb;
vals.virtMemKB = ( vsize / 1024 ) - vals.physMemKB;
vals.userMilliseconds = ( utime * 1000 ) / sysconf( _SC_CLK_TCK );
vals.sysMilliseconds = ( stime * 1000 ) / sysconf( _SC_CLK_TCK );
#elif defined(__APPLE__)
// http://stackoverflow.com/a/1911863/382458
#elif defined(_WIN32)
// http://stackoverflow.com/a/282220/382458 and http://stackoverflow.com/a/64166/382458
PROCESS_MEMORY_COUNTERS MemoryCntrs;
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
long page_size_kb = 1024;
ULARGE_INTEGER kTime, uTime;
if( GetProcessMemoryInfo( GetCurrentProcess(), &MemoryCntrs, sizeof( MemoryCntrs ) ) ) {
vals.physMemKB = MemoryCntrs.PeakWorkingSetSize / page_size_kb;
vals.virtMemKB = MemoryCntrs.PeakPagefileUsage / page_size_kb;
} else {
vals.physMemKB = 0;
vals.virtMemKB = 0;
}
if( GetProcessTimes( GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime ) ) {
assert( sizeof( FILETIME ) == sizeof( ULARGE_INTEGER ) );
memcpy( &kTime, &KernelTime, sizeof( FILETIME ) );
memcpy( &uTime, &UserTime, sizeof( FILETIME ) );
vals.userMilliseconds = ( long )( uTime.QuadPart / 100000L );
vals.sysMilliseconds = ( long )( kTime.QuadPart / 100000L );
} else {
vals.userMilliseconds = 0;
vals.sysMilliseconds = 0;
}
#else
#warning Unknown platform!
#endif // __linux__
return vals;
}
// --------------------- benchmark class ---------------------
benchmark::benchmark( std::string description, bool debugMessages, std::ostream & o_stream ): ostr( o_stream ),
descr( description ), debug( debugMessages ), stopped( false ) {
initialVals = getMemAndTime( );
}
benchmark::~benchmark() {
if( !stopped ) {
stop( );
if( debug ) {
ostr << "benchmark::~benchmark(): stop was not called before destructor!" << std::endl;
}
out( );
}
}
void benchmark::stop( ) {
if( stopped ) {
std::cerr << "benchmark::stop(): tried to stop a benchmark that was already stopped!" << std::endl;
} else {
laterVals = getMemAndTime( );
stopped = true;
}
}
benchVals benchmark::get( ) {
if( !stopped ) {
laterVals = getMemAndTime( );
}
benchVals delta;
delta.physMemKB = laterVals.physMemKB - initialVals.physMemKB;
delta.virtMemKB = laterVals.virtMemKB - initialVals.virtMemKB;
delta.sysMilliseconds = laterVals.sysMilliseconds - initialVals.sysMilliseconds;
delta.userMilliseconds = laterVals.userMilliseconds - initialVals.userMilliseconds;
//If vm is negative, the memory had been requested before initialVals was set. Don't count it
if( delta.virtMemKB < 0 ) {
delta.physMemKB -= delta.virtMemKB;
delta.virtMemKB = 0;
}
return delta;
}
void benchmark::reset( std::string description ) {
descr = description;
reset();
}
void benchmark::reset( ) {
stopped = false;
initialVals = getMemAndTime();
}
std::string benchmark::str( ) {
return str( get( ) );
}
void benchmark::out() {
ostr << str( ) << std::endl;
}
std::string benchmark::str( const benchVals & bv ) {
std::stringstream ss;
ss << descr << " Physical memory: " << bv.physMemKB << "kb; Virtual memory: " << bv.virtMemKB;
ss << "kb; User CPU time: " << bv.userMilliseconds << "ms; System CPU time: " << bv.sysMilliseconds << "ms";
return ss.str();
}