View Javadoc

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