87 lines
2.5 KiB
Python
87 lines
2.5 KiB
Python
import os
|
|
import re
|
|
import sys
|
|
from collections import defaultdict
|
|
|
|
import matplotlib
|
|
|
|
matplotlib.use("Agg")
|
|
import matplotlib.pyplot as plt
|
|
|
|
if len(sys.argv) < 3:
|
|
print("Использование: python3 exporter.py <logfile> <output_dir>")
|
|
sys.exit(1)
|
|
|
|
logfile = sys.argv[1]
|
|
out_dir = sys.argv[2]
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
base = os.path.splitext(os.path.basename(logfile))[0]
|
|
|
|
pattern = re.compile(
|
|
r"(START|END) PID=(\d+) PPID=(\d+) depth=(\d+) size=(\d+) time=([\d.]+)"
|
|
)
|
|
events = defaultdict(dict)
|
|
|
|
with open(logfile, encoding="utf-8") as f:
|
|
for line in f:
|
|
m = pattern.search(line)
|
|
if not m:
|
|
continue
|
|
typ, pid, ppid, depth, size, t = m.groups()
|
|
key = (int(pid), int(depth), int(size))
|
|
events[key][typ] = float(t)
|
|
events[key]["pid"] = int(pid)
|
|
events[key]["ppid"] = int(ppid)
|
|
events[key]["depth"] = int(depth)
|
|
events[key]["size"] = int(size)
|
|
|
|
rows = []
|
|
for v in events.values():
|
|
if "START" in v and "END" in v:
|
|
rows.append(v)
|
|
|
|
if not rows:
|
|
print("В логе нет полных START/END событий")
|
|
sys.exit(1)
|
|
|
|
rows.sort(key=lambda r: (r["START"], r["depth"], r["pid"]))
|
|
t0 = min(r["START"] for r in rows)
|
|
|
|
# 1. Временная диаграмма: видно параллельность и время жизни каждого процесса.
|
|
plt.figure(figsize=(12, max(5, len(rows) * 0.35)))
|
|
for y, r in enumerate(rows):
|
|
start = r["START"] - t0
|
|
end = r["END"] - t0
|
|
plt.plot([start, end], [y, y], linewidth=5)
|
|
plt.text(
|
|
end,
|
|
y,
|
|
f" pid={r['pid']} d={r['depth']} n={r['size']}",
|
|
va="center",
|
|
fontsize=8,
|
|
)
|
|
|
|
plt.xlabel("Время от начала, сек")
|
|
plt.ylabel("Процессы/задачи сортировки")
|
|
plt.title(f"Временная диаграмма процессов: {base}")
|
|
plt.grid(True)
|
|
plt.tight_layout()
|
|
plt.savefig(os.path.join(out_dir, f"{base}_timeline.png"))
|
|
plt.close()
|
|
|
|
# 2. Гистограмма глубин: проверка, что дерево дошло до нужной глубины.
|
|
by_depth = defaultdict(int)
|
|
for r in rows:
|
|
by_depth[r["depth"]] += 1
|
|
|
|
plt.figure(figsize=(8, 5))
|
|
xs = sorted(by_depth)
|
|
plt.bar(xs, [by_depth[x] for x in xs])
|
|
plt.xlabel("Глубина рекурсии")
|
|
plt.ylabel("Количество процессов")
|
|
plt.title(f"Распределение процессов по глубине: {base}")
|
|
plt.grid(True, axis="y")
|
|
plt.tight_layout()
|
|
plt.savefig(os.path.join(out_dir, f"{base}_depth_hist.png"))
|
|
plt.close()
|