From 4049e66428a917a5bc99ad1aed43de42d0fb6829 Mon Sep 17 00:00:00 2001 From: pajjilykk Date: Wed, 6 May 2026 10:08:14 +0700 Subject: [PATCH] add missing graph to 1 --- 1/exporter.py | 163 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 148 insertions(+), 15 deletions(-) diff --git a/1/exporter.py b/1/exporter.py index 96e5411..7804142 100644 --- a/1/exporter.py +++ b/1/exporter.py @@ -1,6 +1,9 @@ +import math import os import re +import subprocess import sys +import time import matplotlib.pyplot as plt @@ -52,11 +55,13 @@ def parse_log(path): def build_tree(procs): root = None + for p in procs.values(): if p.ppid in procs: procs[p.ppid].children.append(p) else: root = p + return root @@ -94,18 +99,29 @@ def draw_gantt(ordered): first = min(p.start for p in ordered) - # Создаем карту цветов, чтобы PID всегда имел один и тот же цвет - cmap = plt.get_cmap('tab20') + cmap = plt.get_cmap("tab20") color_map = {p.pid: cmap(i % 20) for i, p in enumerate(ordered)} # ------------------------- - # 1) TREE ORDER (current) + # 1) TREE ORDER # ------------------------- + fig, ax = plt.subplots(figsize=(12, 6)) for i, p in enumerate(ordered): - ax.barh(i, p.duration, left=p.start - first, height=0.6, color=color_map[p.pid]) - ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center") + ax.barh( + i, + p.duration, + left=p.start - first, + height=0.6, + color=color_map[p.pid], + ) + ax.text( + p.start - first, + i, + f"PID {p.pid} ({p.depth})", + va="center", + ) ax.set_yticks(range(len(ordered))) ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in ordered]) @@ -118,20 +134,32 @@ def draw_gantt(ordered): plt.close() # ------------------------- - # 2) PID-SORTED VIEW + # 2) PID ORDER # ------------------------- + pid_order = sorted(ordered, key=lambda p: p.pid) fig, ax = plt.subplots(figsize=(12, 6)) for i, p in enumerate(pid_order): - ax.barh(i, p.duration, left=p.start - first, height=0.6, color=color_map[p.pid]) - ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center") + ax.barh( + i, + p.duration, + left=p.start - first, + height=0.6, + color=color_map[p.pid], + ) + ax.text( + p.start - first, + i, + f"PID {p.pid} ({p.depth})", + va="center", + ) ax.set_yticks(range(len(pid_order))) ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in pid_order]) ax.set_xlabel("Секунд с начала первого процесса") - ax.set_title("Диаграмма процессов (в порядке)") + ax.set_title("Диаграмма процессов (в порядке PID)") ax.invert_yaxis() plt.tight_layout() @@ -139,15 +167,120 @@ def draw_gantt(ordered): plt.close() +# ============================================================ +# PERFORMANCE GRAPH +# ============================================================ + + +def depth_for_process_count(proc_count): + """ + Your C++ program creates processes by recursion depth. + + depth=0 -> 1 process + depth=1 -> 3 processes + depth=2 -> 7 processes + depth=3 -> 15 processes + depth=4 -> 31 processes + depth=5 -> 63 processes + + This function chooses the closest depth for requested process count. + """ + + if proc_count <= 1: + return 0 + + return max(0, math.ceil(math.log2(proc_count + 1)) - 1) + + +def run_process_test(n, proc_count): + max_depth = depth_for_process_count(proc_count) + + cmd = ["./lab1", str(n), str(max_depth)] + + start = time.perf_counter() + + subprocess.run( + cmd, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=False, + ) + + end = time.perf_counter() + + return end - start + + +def draw_performance_graph(): + n = 10000 + proc_counts = list(range(1, 33)) + + times = [] + + print("\nBenchmarking process count performance:") + + for p in proc_counts: + t = run_process_test(n, p) + times.append(t) + print(f"Processes: {p:2d} | Time: {t:.6f} sec") + + base_time = times[0] + + speedup = [base_time / t if t > 0 else 0 for t in times] + + out_path = os.path.join(OUT_DIR, "process_performance.png") + + fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6)) + + # ------------------------- + # TIME GRAPH + # ------------------------- + + ax1.plot(proc_counts, times, "o-") + ax1.set_xlabel("Количество процессов") + ax1.set_ylabel("Время (сек)") + ax1.set_title("Время выполнения") + ax1.grid(True) + + # ------------------------- + # SPEEDUP GRAPH + # ------------------------- + + ax2.plot(proc_counts, speedup, "s-", label="Реальное ускорение") + ax2.plot( + proc_counts, + proc_counts, + "--", + color="black", + alpha=0.3, + label="Идеал", + ) + + ax2.set_xlabel("Количество процессов") + ax2.set_ylabel("Ускорение") + ax2.set_title("Масштабируемость") + ax2.legend() + ax2.grid(True) + + plt.tight_layout() + plt.savefig(out_path) + plt.close() + + print(f"\nPerformance graph saved to: {out_path}") + + def main(): - procs = parse_log(sys.argv[1]) - root = build_tree(procs) - ordered = dfs_order(root) + if len(sys.argv) > 1: + procs = parse_log(sys.argv[1]) + root = build_tree(procs) + ordered = dfs_order(root) - write_md(procs, ordered) - draw_gantt(ordered) + write_md(procs, ordered) + draw_gantt(ordered) - print(f"Outputs saved to: {OUT_DIR}/") + draw_performance_graph() + + print(f"\nOutputs saved to: {OUT_DIR}/") if __name__ == "__main__":