1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/misc/cpu_time_stat.h"
23 #include "nel/misc/common.h"
24 #include "nel/misc/debug.h"
42 // Get absolute ticks value for the whole cpu set
43 bool CCPUTimeStat::getCPUTicks(uint64
& user
, uint64
& nice
, uint64
& system
, uint64
& idle
, uint64
& iowait
)
47 const char* statfile
= "/proc/stat";
48 FILE* f
= nlfopen(statfile
, "r");
54 // cpu [user] [nice] [system] [idle] [iowait] [irq] [softirq]
55 if (fscanf(f
, "cpu %" NL_I64
"u %" NL_I64
"u %" NL_I64
"u %" NL_I64
"u %" NL_I64
"u", &user
, &nice
, &system
, &idle
, &iowait
) != 5)
56 nlwarning("Failed to parse /proc/stat");
66 // Get absolute ticks values for a specified pid
67 bool CCPUTimeStat::getPIDTicks(uint64
& utime
, uint64
& stime
, uint64
& cutime
, uint64
& cstime
, uint pid
)
71 std::string statfile
= NLMISC::toString("/proc/%u/stat", pid
);
72 FILE* f
= nlfopen(statfile
, "r");
78 // pid com sta ppi pgi ses tty tpg fla mif maf cmi cma [utime] [stime] [cutime] [cstime] ...
79 if (fscanf(f
, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %" NL_I64
"u %" NL_I64
"u %" NL_I64
"u %" NL_I64
"u", &utime
, &stime
, &cutime
, &cstime
) != 4)
80 nlwarning("Failed to parse /proc/<pid>/stat");
95 CCPUTimeStat::CCPUTimeStat() : _PID(0), _FirstTime(true), _LastCPUTicks(0), _LastPIDTicks(0)
111 void CCPUTimeStat::peekMeasures()
113 NLMISC::TTime ctime
= NLMISC::CTime::getLocalTime();
115 uint64 u
, n
, s
, i
, io
;
116 uint64 ut
, st
, cut
, cst
;
117 if (getCPUTicks(u
, n
, s
, i
, io
) && getPIDTicks(ut
, st
, cut
, cst
, _PID
))
119 uint64 cpuTicks
= u
+n
+s
+i
+io
;
120 uint64 pidTicks
= ut
+st
+cut
+cst
;
123 if (_LastCPUTicks
== cpuTicks
|| _LastPIDTicks
== pidTicks
)
126 _LastCPUTicks
= cpuTicks
;
127 _CPUUser
.computeDiff(u
);
128 _CPUNice
.computeDiff(n
);
129 _CPUSystem
.computeDiff(s
);
130 _CPUIdle
.computeDiff(i
);
131 _CPUIOWait
.computeDiff(io
);
133 _LastPIDTicks
= pidTicks
;
134 _PIDUTime
.computeDiff(ut
);
135 _PIDSTime
.computeDiff(st
);
136 _PIDCUTime
.computeDiff(cut
);
137 _PIDCSTime
.computeDiff(cst
);
141 uint32 cpuTotal
= _CPUUser
.Diff
+_CPUNice
.Diff
+_CPUSystem
.Diff
+_CPUIdle
.Diff
+_CPUIOWait
.Diff
;
143 _CPUUser
.computeLoad(cpuTotal
, ctime
);
144 _CPUNice
.computeLoad(cpuTotal
, ctime
);
145 _CPUSystem
.computeLoad(cpuTotal
, ctime
);
146 _CPUIdle
.computeLoad(cpuTotal
, ctime
);
147 _CPUIOWait
.computeLoad(cpuTotal
, ctime
);
149 uint32 pidTotal
= _PIDUTime
.Diff
+_PIDSTime
.Diff
+_PIDCUTime
.Diff
+_PIDCSTime
.Diff
;
150 if (pidTotal
> cpuTotal
)
152 // EEK! should not happen!!
156 _PIDUTime
.computeLoad(cpuTotal
, ctime
);
157 _PIDSTime
.computeLoad(cpuTotal
, ctime
);
158 _PIDCUTime
.computeLoad(cpuTotal
, ctime
);
159 _PIDCSTime
.computeLoad(cpuTotal
, ctime
);