This project has retired. For details please refer to its Attic page.
Source code
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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.wake.metrics;
020
021import java.util.concurrent.TimeUnit;
022import java.util.concurrent.atomic.AtomicLong;
023
024/**
025 * Meter that monitors mean throughput and ewma (1m, 5m, 15m) throughput.
026 */
027public class Meter {
028
029  private static final long TICK_INTERVAL = TimeUnit.SECONDS.toNanos(5);
030
031  private final AtomicLong count = new AtomicLong();
032  private final long startTime;
033  private final AtomicLong lastTick;
034
035  private final EWMA m1Thp;
036  private final EWMA m5Thp;
037  private final EWMA m15Thp;
038
039  private final String name;
040
041  /**
042   * Constructs a meter.
043   *
044   * @param name the name of the meter
045   */
046  public Meter(final String name) {
047    this.name = name;
048    this.m1Thp = new EWMA(EWMAParameters.M1_ALPHA, EWMAParameters.INTERVAL, TimeUnit.SECONDS);
049    this.m5Thp = new EWMA(EWMAParameters.M5_ALPHA, EWMAParameters.INTERVAL, TimeUnit.SECONDS);
050    this.m15Thp = new EWMA(EWMAParameters.M15_ALPHA, EWMAParameters.INTERVAL, TimeUnit.SECONDS);
051    this.startTime = getTick();
052    this.lastTick = new AtomicLong(startTime);
053  }
054
055  /**
056   * Gets the name of the meter.
057   *
058   * @return the meter name
059   */
060  public String getName() {
061    return name;
062  }
063
064  /**
065   * Marks the number of events.
066   *
067   * @param n the number of events
068   */
069  public void mark(final long n) {
070    tickIfNecessary();
071    count.addAndGet(n);
072    m1Thp.update(n);
073    m5Thp.update(n);
074    m15Thp.update(n);
075  }
076
077  /**
078   * Gets the count.
079   *
080   * @return the count
081   */
082  public long getCount() {
083    return count.get();
084  }
085
086  /**
087   * Gets the mean throughput.
088   *
089   * @return the mean throughput
090   */
091  public double getMeanThp() {
092    if (getCount() == 0) {
093      return 0.0;
094    } else {
095      final double elapsed = getTick() - startTime;
096      return getCount() / elapsed * TimeUnit.SECONDS.toNanos(1);
097    }
098  }
099
100  /**
101   * Gets the 1-minute EWMA throughput.
102   *
103   * @return the 1-minute EWMA throughput
104   */
105  public double get1mEWMAThp() {
106    tickIfNecessary();
107    return m1Thp.getRate(TimeUnit.SECONDS);
108  }
109
110  /**
111   * Gets the 5-minute EWMA throughput.
112   *
113   * @return the 5-minute EWMA throughput
114   */
115  public double get5mEWMAThp() {
116    tickIfNecessary();
117    return m5Thp.getRate(TimeUnit.SECONDS);
118  }
119
120  /**
121   * Gets the 15-minute EWMA throughput.
122   *
123   * @return the 15-minute EWMA throughput
124   */
125  public double get15mEWMAThp() {
126    tickIfNecessary();
127    return m15Thp.getRate(TimeUnit.SECONDS);
128  }
129
130  private long getTick() {
131    return System.nanoTime();
132  }
133
134  private void tickIfNecessary() {
135    final long oldTick = lastTick.get();
136    final long newTick = getTick();
137    final long age = newTick - oldTick;
138    if (age > TICK_INTERVAL && lastTick.compareAndSet(oldTick, newTick)) {
139      final long requiredTicks = age / TICK_INTERVAL;
140      for (long i = 0; i < requiredTicks; i++) {
141        m1Thp.tick();
142        m5Thp.tick();
143        m15Thp.tick();
144      }
145    }
146  }
147}