| 98 | } |
| 99 | |
| 100 | ProcessResources ProcessSampler::Sample(int pid) { |
| 101 | ProcessResources out; |
| 102 | if (pid <= 0) return out; |
| 103 | out.rss_bytes = ReadRssBytes(pid); |
| 104 | |
| 105 | const uint64_t ticks_now = ReadCpuTicks(pid); |
| 106 | const int64_t wall_now = WallClockMs(); |
| 107 | const long clk_tck = ::sysconf(_SC_CLK_TCK); |
| 108 | if (ticks_now == 0 || clk_tck <= 0) return out; |
| 109 | |
| 110 | std::lock_guard<std::mutex> lock(mutex_); |
| 111 | auto it = last_.find(pid); |
| 112 | if (it != last_.end() && it->second.cpu_ticks > 0 && wall_now > it->second.wall_ms) { |
| 113 | const uint64_t d_ticks = (ticks_now > it->second.cpu_ticks) |
| 114 | ? (ticks_now - it->second.cpu_ticks) |
| 115 | : 0; |
| 116 | const int64_t d_wall_ms = wall_now - it->second.wall_ms; |
| 117 | if (d_wall_ms > 0) { |
| 118 | // d_ticks/clk_tck = CPU seconds consumed; divide by wall seconds |
| 119 | // (d_wall_ms/1000) and multiply by 100 to express as "% of one |
| 120 | // logical core". |
| 121 | const double cpu_seconds = static_cast<double>(d_ticks) / static_cast<double>(clk_tck); |
| 122 | const double wall_seconds = static_cast<double>(d_wall_ms) / 1000.0; |
| 123 | out.cpu_percent = (cpu_seconds / wall_seconds) * 100.0; |
| 124 | if (out.cpu_percent < 0.0) out.cpu_percent = 0.0; |
| 125 | } |
| 126 | } |
| 127 | last_[pid] = PidSample{.cpu_ticks = ticks_now, .wall_ms = wall_now}; |
| 128 | return out; |
| 129 | } |
| 130 | |
| 131 | void ProcessSampler::Forget(int pid) { |
| 132 | std::lock_guard<std::mutex> lock(mutex_); |
no test coverage detected