1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2017 - ROLI Ltd.
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
27 /** A timer for measuring performance of code and dumping the results to a file.
28 
29     e.g. @code
30 
31         PerformanceCounter pc ("fish", 50, "/temp/myfishlog.txt");
32 
33         for (;;)
34         {
35             pc.start();
36 
37             doSomethingFishy();
38 
39             pc.stop();
40         }
41     @endcode
42 
43     In this example, the time of each period between calling start/stop will be
44     measured and averaged over 50 runs, and the results printed to a file
45     every 50 times round the loop.
46 
47     @tags{Core}
48 */
49 class JUCE_API  PerformanceCounter
50 {
51 public:
52     //==============================================================================
53     /** Creates a PerformanceCounter object.
54 
55         @param counterName      the name used when printing out the statistics
56         @param runsPerPrintout  the number of start/stop iterations before calling
57                                 printStatistics()
58         @param loggingFile      a file to dump the results to - if this is File(),
59                                 the results are just written to the debugger output
60     */
61     PerformanceCounter (const String& counterName,
62                         int runsPerPrintout = 100,
63                         const File& loggingFile = File());
64 
65     /** Destructor. */
66     ~PerformanceCounter();
67 
68     //==============================================================================
69     /** Starts timing.
70         @see stop
71     */
72     void start() noexcept;
73 
74     /** Stops timing and prints out the results.
75 
76         The number of iterations before doing a printout of the
77         results is set in the constructor.
78 
79         @see start
80     */
81     bool stop();
82 
83     /** Dumps the current metrics to the debugger output and to a file.
84 
85         As well as using Logger::outputDebugString to print the results,
86         this will write then to the file specified in the constructor (if
87         this was valid).
88     */
89     void printStatistics();
90 
91     /** Holds the current statistics. */
92     struct Statistics
93     {
94         Statistics() noexcept;
95 
96         void clear() noexcept;
97         String toString() const;
98 
99         void addResult (double elapsed) noexcept;
100 
101         String name;
102         double averageSeconds;
103         double maximumSeconds;
104         double minimumSeconds;
105         double totalSeconds;
106         int64 numRuns;
107     };
108 
109     /** Returns a copy of the current stats, and resets the internal counter. */
110     Statistics getStatisticsAndReset();
111 
112 private:
113     //==============================================================================
114     Statistics stats;
115     int64 runsPerPrint, startTime;
116     File outputFile;
117 
118     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PerformanceCounter)
119 };
120 
121 
122 //==============================================================================
123 /**
124     Simple RAII class for measuring the time spent in a scope.
125 
126     Example:
127 
128     {
129         double timeSec;
130 
131         {
132             ScopedTimeMeasurement m (timeSec);
133             doSomething();
134         }
135 
136         Logger::writeToLog ("doSomething() took " + String (timeSec) + "seconds");
137     }
138 
139     @param resultInSeconds The result of the measurement will be stored in this variable.
140 
141     @tags{Core}
142 */
143 class JUCE_API  ScopedTimeMeasurement
144 {
145 public:
ScopedTimeMeasurement(double & resultInSeconds)146     ScopedTimeMeasurement (double& resultInSeconds) noexcept
147         : result (resultInSeconds)
148     {
149         result = 0.0;
150     }
151 
~ScopedTimeMeasurement()152     ~ScopedTimeMeasurement()
153     {
154         static auto scaler = 1.0 / static_cast<double> (Time::getHighResolutionTicksPerSecond());
155         result = static_cast<double> (Time::getHighResolutionTicks() - startTimeTicks) * scaler;
156     }
157 
158 private:
159     int64 startTimeTicks = Time::getHighResolutionTicks();
160     double& result;
161 
162     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScopedTimeMeasurement)
163 };
164 
165 } // namespace juce
166