summaryrefslogtreecommitdiffhomepage
path: root/cpuload.cpp
blob: 77abc3e3960e694503086a063c0a4018e4f01a2f (plain)
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
#include "cpuload.h"

#include <chrono>
#include <numeric>

#include <libreichwein/file.h>
#include <libreichwein/stringhelper.h>

int get_number_of_cpus()
{
  int result{};
  std::string stat = Reichwein::File::getFile("/proc/stat");
  std::vector<std::string> lines = Reichwein::Stringhelper::split(stat, "\n");
  for (const auto& line: lines) {
    std::vector<std::string> words = Reichwein::Stringhelper::split(line, " ");
    // /proc/stat line, e.g.: cpu0 1132 34 1441 11311718 3675 127 438
    if (words.size() >= 8) {
      if (words[0].size() > 3 && words[0].substr(0, 3) == "cpu") {
        ++result;
      }
    }
  }
  return result;
}

// returns empty vector if no data is available yet
// Note: to be called several times, because data is generated differentially from /proc/stat
std::vector<int> get_cpu_loads()
{
  using clock_type = std::chrono::high_resolution_clock;
  static int number_of_cpus = get_number_of_cpus();
  static std::vector<int> stat_cpus_sum(number_of_cpus);
  static std::vector<int> stat_cpus_idle(number_of_cpus);
  static std::chrono::time_point<clock_type> timestamp{};

  std::string stat = Reichwein::File::getFile("/proc/stat");

  std::vector<std::string> lines = Reichwein::Stringhelper::split(stat, "\n");

  std::vector<int> result;

  int i = 0;
  for (const auto& line: lines) {
    std::vector<std::string> words = Reichwein::Stringhelper::split(line, " ");
    // /proc/stat line, e.g.: cpu0 1132 34 1441 11311718 3675 127 438
    // idle value is at index 4
    if (words.size() >= 8) {
      if (words[0].size() > 3 && words[0].substr(0, 3) == "cpu") {
        uint64_t sum = std::accumulate(words.begin() + 1, words.end(), uint64_t{}, [](uint64_t sum, const std::string& s){return sum + std::stoull(s);});
        uint64_t idle = std::stoull(words[4]);

        // previous data available
        if (timestamp == std::chrono::time_point<clock_type>{})
        {
          uint64_t sum_diff = sum - stat_cpus_sum[i];
          uint64_t idle_diff = idle - stat_cpus_idle[i];
          int percentage = (sum_diff == 0) ? 0 : ((sum_diff - idle_diff) * 100 / sum_diff);
          result.push_back(percentage);
        }

        stat_cpus_sum[i] = sum;
        stat_cpus_idle[i] = idle;

        ++i;
      }
    }
  }

  return result;
}