001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to you under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations under 015 * the License. 016 */ 017package org.apache.hadoop.hbase.io.hfile; 018 019/** 020 * A nano-second timer. 021 * <p> 022 * Copied from 023 * <a href="https://issues.apache.org/jira/browse/HADOOP-3315">hadoop-3315 tfile</a>. 024 * Remove after tfile is committed and use the tfile version of this class 025 * instead.</p> 026 */ 027public class NanoTimer { 028 private long last = -1; 029 private boolean started = false; 030 private long cumulate = 0; 031 032 /** 033 * Constructor 034 * 035 * @param start 036 * Start the timer upon construction. 037 */ 038 public NanoTimer(boolean start) { 039 if (start) this.start(); 040 } 041 042 /** 043 * Start the timer. 044 * 045 * Note: No effect if timer is already started. 046 */ 047 public void start() { 048 if (!this.started) { 049 this.last = System.nanoTime(); 050 this.started = true; 051 } 052 } 053 054 /** 055 * Stop the timer. 056 * 057 * Note: No effect if timer is already stopped. 058 */ 059 public void stop() { 060 if (this.started) { 061 this.started = false; 062 this.cumulate += System.nanoTime() - this.last; 063 } 064 } 065 066 /** 067 * Read the timer. 068 * 069 * @return the elapsed time in nano-seconds. Note: If the timer is never 070 * started before, -1 is returned. 071 */ 072 public long read() { 073 if (!readable()) return -1; 074 075 return this.cumulate; 076 } 077 078 /** 079 * Reset the timer. 080 */ 081 public void reset() { 082 this.last = -1; 083 this.started = false; 084 this.cumulate = 0; 085 } 086 087 /** 088 * Checking whether the timer is started 089 * 090 * @return true if timer is started. 091 */ 092 public boolean isStarted() { 093 return this.started; 094 } 095 096 /** 097 * Format the elapsed time to a human understandable string. 098 * 099 * Note: If timer is never started, "ERR" will be returned. 100 */ 101 @Override 102 public String toString() { 103 if (!readable()) { 104 return "ERR"; 105 } 106 107 return NanoTimer.nanoTimeToString(this.cumulate); 108 } 109 110 /** 111 * A utility method to format a time duration in nano seconds into a human 112 * understandable stirng. 113 * 114 * @param t 115 * Time duration in nano seconds. 116 * @return String representation. 117 */ 118 public static String nanoTimeToString(long t) { 119 if (t < 0) return "ERR"; 120 121 if (t == 0) return "0"; 122 123 if (t < 1000) { 124 return t + "ns"; 125 } 126 127 double us = (double) t / 1000; 128 if (us < 1000) { 129 return String.format("%.2fus", us); 130 } 131 132 double ms = us / 1000; 133 if (ms < 1000) { 134 return String.format("%.2fms", ms); 135 } 136 137 double ss = ms / 1000; 138 if (ss < 1000) { 139 return String.format("%.2fs", ss); 140 } 141 142 long mm = (long) ss / 60; 143 ss -= mm * 60; 144 long hh = mm / 60; 145 mm -= hh * 60; 146 long dd = hh / 24; 147 hh -= dd * 24; 148 149 if (dd > 0) { 150 return String.format("%dd%dh", dd, hh); 151 } 152 153 if (hh > 0) { 154 return String.format("%dh%dm", hh, mm); 155 } 156 157 if (mm > 0) { 158 return String.format("%dm%.1fs", mm, ss); 159 } 160 161 return String.format("%.2fs", ss); 162 163 /** 164 * StringBuilder sb = new StringBuilder(); String sep = ""; 165 * 166 * if (dd > 0) { String unit = (dd > 1) ? "days" : "day"; 167 * sb.append(String.format("%s%d%s", sep, dd, unit)); sep = " "; } 168 * 169 * if (hh > 0) { String unit = (hh > 1) ? "hrs" : "hr"; 170 * sb.append(String.format("%s%d%s", sep, hh, unit)); sep = " "; } 171 * 172 * if (mm > 0) { String unit = (mm > 1) ? "mins" : "min"; 173 * sb.append(String.format("%s%d%s", sep, mm, unit)); sep = " "; } 174 * 175 * if (ss > 0) { String unit = (ss > 1) ? "secs" : "sec"; 176 * sb.append(String.format("%s%.3f%s", sep, ss, unit)); sep = " "; } 177 * 178 * return sb.toString(); 179 */ 180 } 181 182 private boolean readable() { 183 return this.last != -1; 184 } 185 186 /** 187 * Simple tester. 188 * 189 * @param args 190 */ 191 public static void main(String[] args) { 192 long i = 7; 193 194 for (int x = 0; x < 20; ++x, i *= 7) { 195 System.out.println(NanoTimer.nanoTimeToString(i)); 196 } 197 } 198} 199