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