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.util; 019 020import org.apache.yetus.audience.InterfaceAudience; 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024/** 025 * The purpose of introduction of {@link MovingAverage} mainly is to measure execution time of a 026 * specific method, which can help us to know its performance fluctuation in response to different 027 * machine states or situations, better case, then to act accordingly. <br> 028 * In different situation, different {@link MovingAverage} algorithm can be used based on needs. 029 */ 030@InterfaceAudience.Private 031public abstract class MovingAverage<T> { 032 private final static Logger LOG = LoggerFactory.getLogger(MovingAverage.class); 033 034 protected final String label; 035 036 protected MovingAverage(String label) { 037 this.label = label; 038 } 039 040 /** 041 * Mark start time of an execution. 042 * @return time in ns. 043 */ 044 protected long start() { 045 return System.nanoTime(); 046 } 047 048 /** 049 * Mark end time of an execution, and return its interval. 050 * @param startTime start time of an execution 051 * @return elapsed time 052 */ 053 protected long stop(long startTime) { 054 return System.nanoTime() - startTime; 055 } 056 057 /** 058 * Measure elapsed time of a measurable method. 059 * @param measurable method implements {@link TimeMeasurable} 060 * @return T it refers to the original return type of the measurable method 061 */ 062 public T measure(TimeMeasurable<T> measurable) { 063 long startTime = start(); 064 LOG.trace("{} - start to measure at: {} ns.", label, startTime); 065 // Here may throw exceptions which should be taken care by caller, not here. 066 // If exception occurs, this time wouldn't count. 067 T result = measurable.measure(); 068 long elapsed = stop(startTime); 069 LOG.trace("{} - elapse: {} ns.", label, elapsed); 070 updateMostRecentTime(elapsed); 071 return result; 072 } 073 074 /** 075 * Update the most recent data. 076 * @param elapsed elapsed time of the most recent measurement 077 */ 078 protected abstract void updateMostRecentTime(long elapsed); 079 080 /** 081 * Get average execution time of the measured method. 082 * @return average time in ns 083 */ 084 public abstract double getAverageTime(); 085}