1 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla code.
17 * The Initial Developer of the Original Code is
18 * Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2009
20 * the Initial Developer. All Rights Reserved.
23 * Vladimir Vukicevic <vladimir@pobox.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef mozilla_FunctionTimer_h
40 #define mozilla_FunctionTimer_h
44 #include "mozilla/TimeStamp.h"
46 #include "nsAutoPtr.h"
48 #if defined(NS_FORCE_FUNCTION_TIMER) && !defined(NS_FUNCTION_TIMER)
49 #define NS_FUNCTION_TIMER
56 #ifdef NS_FUNCTION_TIMER
59 #define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
60 #elif defined(_MSC_VER)
61 #define MOZ_FUNCTION_NAME __FUNCTION__
63 #warning "Define a suitable MOZ_FUNCTION_NAME for this platform"
64 #define MOZ_FUNCTION_NAME ""
67 // Add a timer for this function, from this declaration until the
68 // function returns. The function name will be used as the
69 // log string, and both function entry and exit will be printed.
70 #define NS_TIME_FUNCTION \
71 mozilla::FunctionTimer ft__autogen("%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
73 // Add a timer for this block, but print only a) if the exit time is
74 // greater than the given number of milliseconds; or b) if the
75 // mark-to-mark time is greater than the given number of milliseconds.
76 // No function entry will be printed. If the value given is negative,
77 // no function entry or exit will ever be printed, but all marks will.
78 #define NS_TIME_FUNCTION_MIN(_ms) \
79 mozilla::FunctionTimer ft__autogen((_ms), "%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
81 // Add a timer for this block, but print only marks, not function
82 // entry and exit. The same as calling the above macro with a negative value.
83 #define NS_TIME_FUNCTION_MARK_ONLY \
84 mozilla::FunctionTimer ft__autogen((-1), "%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
86 // Add a timer for this block, using the printf-style format.
87 // Both function entry and exit will be printed.
88 #define NS_TIME_FUNCTION_FMT(...) \
89 mozilla::FunctionTimer ft__autogen(__VA_ARGS__)
91 // Add a timer for this block, using the given minimum number of
92 // milliseconds and the given printf-style format. No function entry
94 #define NS_TIME_FUNCTION_MIN_FMT(_ms, ...) \
95 mozilla::FunctionTimer ft__autogen((_ms), __VA_ARGS__)
97 // Add a midway mark for the current timer; an existing timer must
98 // have already been created using one of the above macros. The
99 // string given by the printf-style format will be logged, as well as
100 // the total elapsed time since the creation of the timer, and the
101 // time since the last mark.
102 #define NS_TIME_FUNCTION_MARK(...) \
103 ft__autogen.Mark(__VA_ARGS__)
105 // A double value representing the time elapsed since NS_TIME_FUNCTION
106 // initialization, in ms.
107 #define NS_TIME_FUNCTION_ELAPSED \
108 ft__autogen.Elapsed()
110 // A double value representing the time elapsed since the last
111 // NS_TIME_FUNCTION_MARK, in ms.
112 #define NS_TIME_FUNCTION_ELAPSED_SINCE_MARK \
113 ft__autogen.ElapsedSinceMark
115 // A TimeDuration value representing the elapsed time between the
116 // last logged event of any sort and the app startup.
117 #define NS_TIME_FUNCTION_LATEST \
118 mozilla::FunctionTimer::LatestSinceStartup()
122 #define NS_TIME_FUNCTION do { } while (0)
123 #define NS_TIME_FUNCTION_MIN(_ms) do { } while (0)
124 #define NS_TIME_FUNCTION_MARK_ONLY do { } while (0)
125 #define NS_TIME_FUNCTION_FMT(...) do { } while (0)
126 #define NS_TIME_FUNCTION_MIN_FMT(_ms, ...) do { } while (0)
127 #define NS_TIME_FUNCTION_MARK(...) do { } while (0)
128 #define NS_TIME_FUNCTION_ELAPSED (0)
129 #define NS_TIME_FUNCTION_ELAPSED_SINCE_MARK (0)
130 #define NS_TIME_FUNCTION_LATEST (mozilla::TimeDuration(0))
136 class NS_COM FunctionTimerLog
139 FunctionTimerLog(const char *fname
);
142 void LogString(const char *str
);
144 TimeDuration
LatestSinceStartup() const;
151 class NS_COM FunctionTimer
153 static nsAutoPtr
<FunctionTimerLog
> sLog
;
157 static unsigned sDepth
;
159 enum { BUF_LOG_LENGTH
= 1024 };
162 static int InitTimers();
164 static int ft_vsnprintf(char *str
, int maxlen
, const char *fmt
, va_list args
);
165 static int ft_snprintf(char *str
, int maxlen
, const char *fmt
, ...);
167 static void LogMessage(const char *s
, ...) {
172 ft_vsnprintf(sBuf1
, sBufSize
, s
, ap
);
173 sLog
->LogString(sBuf1
);
180 void Init(const char *s
, va_list ap
) {
184 ft_vsnprintf(mString
, BUF_LOG_LENGTH
, s
, ap
);
186 ft_snprintf(sBuf1
, sBufSize
, "> (% 3d)%*s|%s%s", mDepth
, mDepth
, " ", mHasMinMs
? "?MINMS " : "", mString
);
187 sLog
->LogString(sBuf1
);
192 inline void TimeInit() {
194 mStart
= TimeStamp::Now();
199 inline double Elapsed() {
201 return (TimeStamp::Now() - mStart
).ToSeconds() * 1000.0;
205 inline double ElapsedSinceMark() {
207 return (TimeStamp::Now() - mLastMark
).ToSeconds() * 1000.0;
211 static inline TimeDuration
LatestSinceStartup() {
212 return sLog
? sLog
->LatestSinceStartup() : TimeDuration(0);
215 FunctionTimer(double minms
, const char *s
, ...)
216 : mMinMs(minms
), mHasMinMs(PR_TRUE
),
217 mEnabled(sLog
&& s
&& *s
), mDepth(++sDepth
)
227 FunctionTimer(const char *s
, ...)
228 : mMinMs(0.0), mHasMinMs(PR_FALSE
),
229 mEnabled(sLog
&& s
&& *s
), mDepth(++sDepth
)
239 void Mark(const char *s
, ...)
245 ft_vsnprintf(sBuf1
, sBufSize
, s
, ap
);
247 TimeStamp
now(TimeStamp::Now());
248 double ms
= (now
- mStart
).ToSeconds() * 1000.0;
249 double msl
= (now
- mLastMark
).ToSeconds() * 1000.0;
252 ft_snprintf(sBuf2
, sBufSize
, "* (% 3d)%*s|%s%9.2f ms (%9.2f ms total) - %s [%s]", mDepth
, mDepth
, " ",
253 (!mHasMinMs
|| mMinMs
< 0.0 || msl
> mMinMs
) ? "<MINMS " : "", msl
, ms
, mString
, sBuf1
);
254 sLog
->LogString(sBuf2
);
262 TimeStamp
now(TimeStamp::Now());
263 double ms
= (now
- mStart
).ToSeconds() * 1000.0;
264 double msl
= (now
- mLastMark
).ToSeconds() * 1000.0;
266 ft_snprintf(sBuf1
, sBufSize
, "< (% 3d)%*s|%s%9.2f ms (%9.2f ms total) - %s", mDepth
, mDepth
, " ",
267 (!mHasMinMs
|| (mMinMs
>= 0.0 && msl
> mMinMs
)) ? "" : "<MINMS ", msl
, ms
, mString
);
268 sLog
->LogString(sBuf1
);
274 TimeStamp mStart
, mLastMark
;
276 char mString
[BUF_LOG_LENGTH
+1];
277 const PRBool mHasMinMs
;
278 const PRBool mEnabled
;
279 const unsigned mDepth
;
282 } // namespace mozilla
284 #endif // mozilla_FunctionTimer_h