1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with this
4 * work for additional information regarding copyright ownership. The ASF
5 * licenses this file to you under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17 package org.apache.hadoop.hbase.io.hfile;
18
19 /**
20 * A nano-second timer.
21 * <p>
22 * Copied from
23 * <a href="https://issues.apache.org/jira/browse/HADOOP-3315">hadoop-3315 tfile</a>.
24 * Remove after tfile is committed and use the tfile version of this class
25 * instead.</p>
26 */
27 public class NanoTimer {
28 private long last = -1;
29 private boolean started = false;
30 private long cumulate = 0;
31
32 /**
33 * Constructor
34 *
35 * @param start
36 * Start the timer upon construction.
37 */
38 public NanoTimer(boolean start) {
39 if (start) this.start();
40 }
41
42 /**
43 * Start the timer.
44 *
45 * Note: No effect if timer is already started.
46 */
47 public void start() {
48 if (!this.started) {
49 this.last = System.nanoTime();
50 this.started = true;
51 }
52 }
53
54 /**
55 * Stop the timer.
56 *
57 * Note: No effect if timer is already stopped.
58 */
59 public void stop() {
60 if (this.started) {
61 this.started = false;
62 this.cumulate += System.nanoTime() - this.last;
63 }
64 }
65
66 /**
67 * Read the timer.
68 *
69 * @return the elapsed time in nano-seconds. Note: If the timer is never
70 * started before, -1 is returned.
71 */
72 public long read() {
73 if (!readable()) return -1;
74
75 return this.cumulate;
76 }
77
78 /**
79 * Reset the timer.
80 */
81 public void reset() {
82 this.last = -1;
83 this.started = false;
84 this.cumulate = 0;
85 }
86
87 /**
88 * Checking whether the timer is started
89 *
90 * @return true if timer is started.
91 */
92 public boolean isStarted() {
93 return this.started;
94 }
95
96 /**
97 * Format the elapsed time to a human understandable string.
98 *
99 * Note: If timer is never started, "ERR" will be returned.
100 */
101 public String toString() {
102 if (!readable()) {
103 return "ERR";
104 }
105
106 return NanoTimer.nanoTimeToString(this.cumulate);
107 }
108
109 /**
110 * A utility method to format a time duration in nano seconds into a human
111 * understandable stirng.
112 *
113 * @param t
114 * Time duration in nano seconds.
115 * @return String representation.
116 */
117 public static String nanoTimeToString(long t) {
118 if (t < 0) return "ERR";
119
120 if (t == 0) return "0";
121
122 if (t < 1000) {
123 return t + "ns";
124 }
125
126 double us = (double) t / 1000;
127 if (us < 1000) {
128 return String.format("%.2fus", us);
129 }
130
131 double ms = us / 1000;
132 if (ms < 1000) {
133 return String.format("%.2fms", ms);
134 }
135
136 double ss = ms / 1000;
137 if (ss < 1000) {
138 return String.format("%.2fs", ss);
139 }
140
141 long mm = (long) ss / 60;
142 ss -= mm * 60;
143 long hh = mm / 60;
144 mm -= hh * 60;
145 long dd = hh / 24;
146 hh -= dd * 24;
147
148 if (dd > 0) {
149 return String.format("%dd%dh", dd, hh);
150 }
151
152 if (hh > 0) {
153 return String.format("%dh%dm", hh, mm);
154 }
155
156 if (mm > 0) {
157 return String.format("%dm%.1fs", mm, ss);
158 }
159
160 return String.format("%.2fs", ss);
161
162 /**
163 * StringBuilder sb = new StringBuilder(); String sep = "";
164 *
165 * if (dd > 0) { String unit = (dd > 1) ? "days" : "day";
166 * sb.append(String.format("%s%d%s", sep, dd, unit)); sep = " "; }
167 *
168 * if (hh > 0) { String unit = (hh > 1) ? "hrs" : "hr";
169 * sb.append(String.format("%s%d%s", sep, hh, unit)); sep = " "; }
170 *
171 * if (mm > 0) { String unit = (mm > 1) ? "mins" : "min";
172 * sb.append(String.format("%s%d%s", sep, mm, unit)); sep = " "; }
173 *
174 * if (ss > 0) { String unit = (ss > 1) ? "secs" : "sec";
175 * sb.append(String.format("%s%.3f%s", sep, ss, unit)); sep = " "; }
176 *
177 * return sb.toString();
178 */
179 }
180
181 private boolean readable() {
182 return this.last != -1;
183 }
184
185 /**
186 * Simple tester.
187 *
188 * @param args
189 */
190 public static void main(String[] args) {
191 long i = 7;
192
193 for (int x = 0; x < 20; ++x, i *= 7) {
194 System.out.println(NanoTimer.nanoTimeToString(i));
195 }
196 }
197 }
198