|
15 | 15 | from lib.utils import safe_makedirs
|
16 | 16 | from lib.utils import print_tail_n
|
17 | 17 | from lib.utils import print_unidiff
|
| 18 | +from lib.utils import get_proc_stat_rss |
18 | 19 |
|
19 | 20 |
|
20 | 21 | class BaseWatcher(object):
|
@@ -178,6 +179,86 @@ def __del__(self):
|
178 | 179 | pass
|
179 | 180 |
|
180 | 181 |
|
| 182 | +class StatisticsMonitor(BaseWatcher): |
| 183 | + def __init__(self, get_not_done_worker_ids, worker_id_to_pid): |
| 184 | + self.get_not_done_worker_ids = get_not_done_worker_ids |
| 185 | + self.worker_id_to_pid = worker_id_to_pid |
| 186 | + self.worker_current_task = dict() |
| 187 | + self.failed_tasks = dict() |
| 188 | + self.rss_results = dict() |
| 189 | + |
| 190 | + # task name set as test name with running configuration |
| 191 | + def get_task_name_conf(self, name, conf): |
| 192 | + if not conf: |
| 193 | + return name |
| 194 | + return name + ':' + conf |
| 195 | + |
| 196 | + def process_result(self, obj): |
| 197 | + # called only once on task run initiated |
| 198 | + if isinstance(obj, WorkerCurrentTask): |
| 199 | + task_name = self.get_task_name_conf(obj.task_name, obj.task_param) |
| 200 | + self.worker_current_task[obj.worker_id] = obj |
| 201 | + self.rss_results[task_name] = get_proc_stat_rss( |
| 202 | + self.worker_id_to_pid[obj.worker_id]) |
| 203 | + |
| 204 | + # called only once on task run finished |
| 205 | + if isinstance(obj, WorkerTaskResult): |
| 206 | + task_name = self.get_task_name_conf(obj.task_id[0], obj.task_id[1]) |
| 207 | + if obj.short_status == 'fail': |
| 208 | + self.failed_tasks[task_name] = 1 |
| 209 | + |
| 210 | + # called on each 'delta_seconds' delay within task run |
| 211 | + def process_timeout(self, delta_seconds): |
| 212 | + rss = None |
| 213 | + worker_ids = self.get_not_done_worker_ids() |
| 214 | + |
| 215 | + running_tasks = [task for worker_id, task |
| 216 | + in self.worker_current_task.items() |
| 217 | + if worker_id in worker_ids] |
| 218 | + for task in running_tasks: |
| 219 | + task_name = self.get_task_name_conf(task.task_name, task.task_param) |
| 220 | + if task_name in self.rss_results: |
| 221 | + rss = get_proc_stat_rss(self.worker_id_to_pid[task.worker_id]) |
| 222 | + if rss > self.rss_results[task_name]: |
| 223 | + self.rss_results[task_name] = rss |
| 224 | + |
| 225 | + # called only once after all tasks finished |
| 226 | + def print_statistics(self): |
| 227 | + top_rss = 5 |
| 228 | + results_sorted = [] |
| 229 | + |
| 230 | + # prepare standalone subpath '<vardir>/statistics' for statistics files |
| 231 | + stats_dir = os.path.join(Options().args.vardir, 'statistics') |
| 232 | + safe_makedirs(stats_dir) |
| 233 | + |
| 234 | + # RSS |
| 235 | + |
| 236 | + # print to stdout RSS statistics for all failed tasks |
| 237 | + if self.failed_tasks: |
| 238 | + color_stdout('RSS of the failed tasks:\n', schema='test_var') |
| 239 | + for task_name in self.failed_tasks: |
| 240 | + if task_name in self.rss_results: |
| 241 | + color_stdout('* %6d %s\n' % (self.rss_results[task_name], task_name), |
| 242 | + schema='test_var') |
| 243 | + |
| 244 | + # print to stdout RSS statistics for some number of most it used tasks |
| 245 | + color_stdout('Up to {} most RSS used tasks in kB:\n' . format(top_rss), schema='test_var') |
| 246 | + results_sorted = sorted(self.rss_results.items(), key=lambda x: x[1], reverse=True) |
| 247 | + count = 0 |
| 248 | + for task_name, rss in results_sorted: |
| 249 | + if count < top_rss: |
| 250 | + color_stdout('* %6s %s\n' % (rss, task_name), schema='test_var') |
| 251 | + count = count + 1 |
| 252 | + color_stdout('-' * 41, "\n", schema='separator') |
| 253 | + |
| 254 | + # print RSS statistics to '<vardir>/statistics/rss.log' file |
| 255 | + filepath = os.path.join(stats_dir, 'rss.log') |
| 256 | + fd = open(filepath, 'w') |
| 257 | + for task_name in self.rss_results: |
| 258 | + fd.write("{} {}\n" . format(task_name, self.rss_results[task_name])) |
| 259 | + fd.close() |
| 260 | + |
| 261 | + |
181 | 262 | class OutputWatcher(BaseWatcher):
|
182 | 263 | def __init__(self):
|
183 | 264 | self.buffer = dict()
|
|
0 commit comments