1 /// Copyright: Copyright (c) 2017-2020 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 module vox.utils.time_measure;
5 
6 import std.stdio : writeln, write, writef, writefln;
7 import vox.all;
8 
9 struct PerPassTimeMeasurements
10 {
11 	TimeMeasurements totalTimes;
12 	TimeMeasurements[] passTimes;
13 	CompilePassGlobal[] passes;
14 	size_t numPasses; // number of passes in the tree of passes
15 
16 	this(size_t numIters, CompilePassGlobal[] passes)
17 	{
18 		this.passes = passes;
19 		totalTimes = TimeMeasurements(numIters);
20 		foreach (passIndex, string name, Duration dur; PassMetaIterator(passes)) ++numPasses;
21 		passTimes = new TimeMeasurements[numPasses];
22 		foreach (ref times; passTimes) times = TimeMeasurements(numIters);
23 	}
24 
25 	void onIteration(size_t iterIndex, Duration iterTime)
26 	{
27 		totalTimes.onIteration(iterIndex, iterTime);
28 		foreach (passIndex, string name, Duration dur; PassMetaIterator(passes))
29 			passTimes[passIndex].onIteration(iterIndex, dur);
30 	}
31 
32 	void print()
33 	{
34 		void printRow(string name, ref TimeMeasurements times)
35 		{
36 			writef("%- 20s", name);
37 			times.print;
38 			writeln;
39 		}
40 
41 		writef("Iterations % 5.0s    ", scaledNumberFmt(totalTimes.numIters));
42 		totalTimes.printHeader; writeln;
43 		foreach (passIndex, string name, Duration dur; PassMetaIterator(passes))
44 			if (name)
45 				printRow(name, passTimes[passIndex]);
46 		printRow("Total", totalTimes);
47 	}
48 
49 	void printTsv()
50 	{
51 		void printRow(string name, ref TimeMeasurements times)
52 		{
53 			writef("%s", name);
54 			times.printTsv;
55 			writeln;
56 		}
57 
58 		writef("Iterations %s", scaledNumberFmt(totalTimes.numIters));
59 		totalTimes.printHeaderTsv; writeln;
60 		foreach (passIndex, string name, Duration dur; PassMetaIterator(passes))
61 			if (name)
62 				printRow(name, passTimes[passIndex]);
63 		printRow("Total", totalTimes);
64 	}
65 }
66 
67 struct TimeMeasurements
68 {
69 	size_t numIters;
70 	Duration[] iterTimes;
71 	Duration totalTime;
72 	Duration avgTime() { return totalTime/numIters; }
73 	Duration minTime = Duration.max;
74 	Duration maxTime = Duration.min;
75 
76 	this(size_t numIters)
77 	{
78 		this.numIters = numIters;
79 		iterTimes = new Duration[numIters];
80 	}
81 
82 	void onIteration(size_t iterIndex, Duration iterTime)
83 	{
84 		iterTimes[iterIndex] = iterTime;
85 		totalTime += iterTime;
86 		minTime = min(iterTime, minTime);
87 		maxTime = max(iterTime, maxTime);
88 	}
89 
90 	enum showNumFirstIters = 3;
91 
92 	void printHeader()
93 	{
94 		if (numIters == 1) {
95 			write("    time");
96 		} else {
97 			foreach (i; 0..min(numIters, showNumFirstIters))
98 				writef("  iter %s", i);
99 			write("   total     avg     min     max");
100 		}
101 	}
102 
103 	void print()
104 	{
105 		if (numIters == 1) {
106 			writef(" % 6.2ss", scaledNumberFmt(iterTimes[0]));
107 		} else {
108 			foreach (i; 0..min(numIters, showNumFirstIters))
109 				writef(" % 6.2ss", scaledNumberFmt(iterTimes[i]));
110 			writef(" % 6.2ss", scaledNumberFmt(totalTime));
111 			writef(" % 6.2ss", scaledNumberFmt(avgTime));
112 			writef(" % 6.2ss", scaledNumberFmt(minTime));
113 			writef(" % 6.2ss", scaledNumberFmt(maxTime));
114 		}
115 	}
116 
117 	void printHeaderTsv()
118 	{
119 		if (numIters == 1) {
120 			write("\ttime");
121 		} else {
122 			foreach (i; 0..min(numIters, showNumFirstIters))
123 				writef("\titer %s", i);
124 			write("\ttotal\tavg\tmin\tmax");
125 		}
126 	}
127 
128 	void printTsv()
129 	{
130 		if (numIters == 1) {
131 			writef("\t%ss", scaledNumberFmt(iterTimes[0]));
132 		} else {
133 			foreach (i; 0..min(numIters, showNumFirstIters))
134 				writef("\t%#ss", scaledNumberFmt(iterTimes[i]));
135 			writef("\t%#ss", scaledNumberFmt(totalTime));
136 			writef("\t%#ss", scaledNumberFmt(avgTime));
137 			writef("\t%#ss", scaledNumberFmt(minTime));
138 			writef("\t%#ss", scaledNumberFmt(maxTime));
139 		}
140 	}
141 }