|
14 | 14 | import gzip
|
15 | 15 | from statistics import mean, median, mode, StatisticsError
|
16 | 16 |
|
| 17 | + |
17 | 18 | # =======================================================================================================
|
18 | 19 | # Helper classes
|
19 | 20 | # =======================================================================================================
|
@@ -102,16 +103,27 @@ def dump_cpu_stats(self, verbose) -> dict:
|
102 | 103 | def dump_cpu_throttle_stats(self, verbose) -> dict:
|
103 | 104 | return self.cpu_throttle.dump_json(verbose)
|
104 | 105 |
|
105 |
| - def insert_memory_stats(self, stats: dict, sample_index: int) -> None: |
106 |
| - if "stat.rss" in stats: |
107 |
| - self.memory.insert_stat(stats["stat.rss"]) |
108 |
| - else: |
109 |
| - print(f"WARNING: The JSON file provided does not contain the 'stat.rss' measurement for sample #{sample_index}. Skipping this sample.") |
110 |
| - if "events.failcnt" in stats: |
111 |
| - self.memory_failcnt.insert_stat(stats["events.failcnt"]) |
| 106 | + def insert_memory_stats(self, stats: dict, sample_index: int, cgroup_version: int) -> None: |
| 107 | + stat_labels = ["stat.rss"] if cgroup_version == 1 else ["stat.anon", "stat.file"] |
| 108 | + rss = 0 |
| 109 | + all_stat_found = True |
| 110 | + for stat_label in stat_labels: |
| 111 | + if stat_label in stats: |
| 112 | + rss += stats[stat_label] |
| 113 | + else: |
| 114 | + print( |
| 115 | + f"WARNING: The JSON file provided does not contain the '{stat_label}' measurement for sample #{sample_index}. Skipping this sample." |
| 116 | + ) |
| 117 | + all_stat_found = False |
| 118 | + if all_stat_found: |
| 119 | + self.memory.insert_stat(rss) |
| 120 | + |
| 121 | + stat_label = "events.failcnt" if cgroup_version == 1 else "events.oom_kill" |
| 122 | + if stat_label in stats: |
| 123 | + self.memory_failcnt.insert_stat(stats[stat_label]) |
112 | 124 | else:
|
113 | 125 | print(
|
114 |
| - f"WARNING: The JSON file provided does not contain the 'events.failcnt' measurement for sample #{sample_index}. Skipping this sample." |
| 126 | + f"WARNING: The JSON file provided does not contain the '{stat_label}' measurement for sample #{sample_index}. Skipping this sample." |
115 | 127 | )
|
116 | 128 |
|
117 | 129 | def dump_memory_stats(self, verbose) -> dict:
|
@@ -152,6 +164,13 @@ def process(self, json_data) -> bool:
|
152 | 164 | print("This tool requires at least 3 samples in the input JSON file. Aborting.")
|
153 | 165 | return False
|
154 | 166 |
|
| 167 | + cgroup_version = 1 |
| 168 | + jheader = json_data["header"] |
| 169 | + if "cgroup_config" in jheader and "version" in jheader["cgroup_config"]: |
| 170 | + cgroup_version = int(jheader["cgroup_config"]["version"]) |
| 171 | + else: |
| 172 | + print(f"WARNING: cgroup version not found in header using default value {cgroup_version}") |
| 173 | + |
155 | 174 | # skip sample 0 because it contains less statistics due to the differential logic that requires some
|
156 | 175 | # initialization sample for most of the stats
|
157 | 176 | first_sample = json_data["samples"][1]
|
@@ -183,7 +202,7 @@ def process(self, json_data) -> bool:
|
183 | 202 | if do_cpu_stats:
|
184 | 203 | self.cgroup_statistics.insert_cpu_stats(sample["cgroup_cpuacct_stats"], nsample)
|
185 | 204 | if do_memory_stats:
|
186 |
| - self.cgroup_statistics.insert_memory_stats(sample["cgroup_memory_stats"], nsample) |
| 205 | + self.cgroup_statistics.insert_memory_stats(sample["cgroup_memory_stats"], nsample, cgroup_version) |
187 | 206 |
|
188 | 207 | self.num_samples_analyzed = len(samples_to_analyze)
|
189 | 208 | # self.cgroup_statistics.insert_io_stats(stats) # cgroup_blkio not yet available
|
|
0 commit comments