1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.base;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21 import static java.util.concurrent.TimeUnit.DAYS;
22 import static java.util.concurrent.TimeUnit.HOURS;
23 import static java.util.concurrent.TimeUnit.MICROSECONDS;
24 import static java.util.concurrent.TimeUnit.MILLISECONDS;
25 import static java.util.concurrent.TimeUnit.MINUTES;
26 import static java.util.concurrent.TimeUnit.NANOSECONDS;
27 import static java.util.concurrent.TimeUnit.SECONDS;
28
29 import com.google.common.annotations.Beta;
30 import com.google.common.annotations.GwtCompatible;
31 import com.google.common.annotations.GwtIncompatible;
32
33 import java.util.concurrent.TimeUnit;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 @Beta
75 @GwtCompatible(emulated = true)
76 public final class Stopwatch {
77 private final Ticker ticker;
78 private boolean isRunning;
79 private long elapsedNanos;
80 private long startTick;
81
82
83
84
85
86
87
88 public static Stopwatch createUnstarted() {
89 return new Stopwatch();
90 }
91
92
93
94
95
96
97
98 public static Stopwatch createUnstarted(Ticker ticker) {
99 return new Stopwatch(ticker);
100 }
101
102
103
104
105
106
107
108 public static Stopwatch createStarted() {
109 return new Stopwatch().start();
110 }
111
112
113
114
115
116
117
118 public static Stopwatch createStarted(Ticker ticker) {
119 return new Stopwatch(ticker).start();
120 }
121
122
123
124
125
126
127
128 @Deprecated
129 Stopwatch() {
130 this(Ticker.systemTicker());
131 }
132
133
134
135
136
137
138
139 @Deprecated
140 Stopwatch(Ticker ticker) {
141 this.ticker = checkNotNull(ticker, "ticker");
142 }
143
144
145
146
147
148
149 public boolean isRunning() {
150 return isRunning;
151 }
152
153
154
155
156
157
158
159 public Stopwatch start() {
160 checkState(!isRunning, "This stopwatch is already running.");
161 isRunning = true;
162 startTick = ticker.read();
163 return this;
164 }
165
166
167
168
169
170
171
172
173 public Stopwatch stop() {
174 long tick = ticker.read();
175 checkState(isRunning, "This stopwatch is already stopped.");
176 isRunning = false;
177 elapsedNanos += tick - startTick;
178 return this;
179 }
180
181
182
183
184
185
186
187 public Stopwatch reset() {
188 elapsedNanos = 0;
189 isRunning = false;
190 return this;
191 }
192
193 private long elapsedNanos() {
194 return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
195 }
196
197
198
199
200
201
202
203
204
205
206
207 public long elapsed(TimeUnit desiredUnit) {
208 return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
209 }
210
211
212
213
214 @GwtIncompatible("String.format()")
215 @Override public String toString() {
216 long nanos = elapsedNanos();
217
218 TimeUnit unit = chooseUnit(nanos);
219 double value = (double) nanos / NANOSECONDS.convert(1, unit);
220
221
222 return String.format("%.4g %s", value, abbreviate(unit));
223 }
224
225 private static TimeUnit chooseUnit(long nanos) {
226 if (DAYS.convert(nanos, NANOSECONDS) > 0) {
227 return DAYS;
228 }
229 if (HOURS.convert(nanos, NANOSECONDS) > 0) {
230 return HOURS;
231 }
232 if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
233 return MINUTES;
234 }
235 if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
236 return SECONDS;
237 }
238 if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
239 return MILLISECONDS;
240 }
241 if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
242 return MICROSECONDS;
243 }
244 return NANOSECONDS;
245 }
246
247 private static String abbreviate(TimeUnit unit) {
248 switch (unit) {
249 case NANOSECONDS:
250 return "ns";
251 case MICROSECONDS:
252 return "\u03bcs";
253 case MILLISECONDS:
254 return "ms";
255 case SECONDS:
256 return "s";
257 case MINUTES:
258 return "min";
259 case HOURS:
260 return "h";
261 case DAYS:
262 return "d";
263 default:
264 throw new AssertionError();
265 }
266 }
267 }