experimental SVG-based video rendering engine made for music videos. React to MIDI or arbitrary signals from your DAW through "probe" VSTs
1import os
2from pathlib import Path
3from subprocess import run
4from sys import argv
5from time import time_ns
6
7from rich.console import Console
8from rich.table import Table
9
10here = Path(__file__).parent
11
12ignored_tasks = []
13
14compare_with = ""
15if len(argv) > 1:
16 compare_with = Path(argv[1]).read_text(encoding="utf-8").strip()
17 compare_with = {
18 (line.split(",")[0], float(line.split(",")[1]), int(line.split(",")[2]))
19 for line in compare_with.splitlines()[1:]
20 }
21 print(compare_with)
22
23
24def avg(numbers: list[float]):
25 return sum(numbers) / len(numbers)
26
27
28end = 0
29start = 0
30
31if not Path("timings.log").exists():
32 start = time_ns()
33 result = run(
34 ["just", "schedule-hell", here.parent / "out.mp4", "--duration 5", "--resolution 320"],
35 capture_output=True,
36 env=os.environ | {"RUST_LOG": "debug", "RUST_BACKTRACE": "full"},
37 )
38 end = time_ns()
39
40 Path("timings.log").write_bytes(result.stdout + result.stderr)
41
42timings = [
43 line.split(" took ")
44 for line in Path("timings.log").read_text(encoding="utf-8").splitlines()
45 if " took " in line
46]
47
48
49def parse_duration(duration_string: str) -> float:
50 if " " in duration_string:
51 return sum(parse_duration(part) for part in duration_string.split(" "))
52 try:
53 figure = float(duration_string.strip("msµ"))
54 except ValueError:
55 return None
56
57 if "µs" in duration_string:
58 return figure * 1e-3
59 if "ms" in duration_string:
60 return figure
61 if "s" in duration_string:
62 return figure * 1e3
63 else:
64 return figure
65
66 raise ValueError(f"Duration string {duration_string!r} has unsupported unit")
67
68
69timings = [
70 (label.split("] ")[1], parse_duration(timing))
71 for label, timing in timings
72 if parse_duration(timing)
73]
74
75per_function: dict[str, list[float]] = {function: [] for function, _ in timings}
76
77for function, timing in timings:
78 per_function[function].append(timing)
79
80averages: list[tuple[str, float, int]] = [
81 (function, avg(timings), len(timings)) for function, timings in per_function.items()
82] + [
83 ("_Total_", (end - start) / 1e6, 1),
84]
85
86averages.sort(key=lambda item: item[1])
87
88header = ["Tâche", "Durée [ms]", "#"]
89
90if compare_with:
91 formatted_results = []
92 for function, timing_after, count_after in averages:
93 if function not in {function for function, _, _ in compare_with}:
94 continue
95 timing_before = next(
96 (timing for fn, timing, _ in compare_with if fn == function),
97 None,
98 )
99 count_before = next(
100 (count for fn, _, count in compare_with if fn == function),
101 None,
102 )
103 if timing_before is None or count_before is None:
104 continue
105 if function in ignored_tasks:
106 continue
107
108 formatted_results.append(
109 [
110 function,
111 f"{timing_after:.3f}",
112 f"{timing_before:.3f}",
113 (
114 f"{timing_after - timing_before:+.3f}"
115 if f"{timing_after - timing_before:.3f}" != "-0.000"
116 else "±0"
117 ),
118 f"{count_after}",
119 f"{count_before}",
120 (
121 f"{count_after - count_before:+}"
122 if count_after != count_before
123 else "±0"
124 ),
125 ]
126 )
127
128 header = [
129 "Tâche",
130 "Durée [ms]",
131 "Durée [ms] avant",
132 "Différence [±ms]",
133 "# après",
134 "# avant",
135 "Différence",
136 ]
137else:
138 formatted_results = [
139 [function, f"{timing:.3f}", f"{count}"] for function, timing, count in averages
140 ]
141
142
143def to_csv(lists: list[list[str]]):
144 return "\r\n".join(
145 ",".join(cell.replace(",", "_") for cell in line) for line in lists
146 )
147
148
149table = Table(*header)
150for row in formatted_results:
151 table.add_row(*row)
152Console().print(table)
153
154Path("results.csv").write_text(
155 to_csv(
156 [
157 header,
158 *[
159 [task, *things]
160 for task, *things in formatted_results
161 if task not in ignored_tasks
162 ],
163 ]
164 ),
165 encoding="utf8",
166)