/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.addthis.basis.util; import java.util.concurrent.atomic.AtomicLong; /** * A class for simple event per second benchmarking */ public final class Bench { public Bench() { this(new String[]{"tick"}, 1000); } public Bench(String name, long rate) { this(new String[]{name}, rate); } @SuppressWarnings("unchecked") public Bench(java.util.EnumSet set, long rate) { Enum e[] = new Enum[set.size()]; set.toArray(e); String nm[] = new String[e.length]; for (int i = 0; i < nm.length; i++) { nm[i] = e[i].name(); } setNames(nm); setPeriod(rate); mark(); marks = 0; } public Bench(String names[], long rate) { setNames(names); setPeriod(rate); mark(); marks = 0; } private long mark; private long rate; private String names[]; private AtomicLong counts[]; private long rates[]; private long marks; public void setNames(String name[]) { assert (name != null && name.length > 0); this.names = name; this.rates = new long[name.length]; this.counts = new AtomicLong[name.length]; for (int i = 0; i < name.length; i++) { counts[i] = new AtomicLong(0); } } public void setPeriod(long rate) { this.rate = rate; } public long getPeriod() { return rate; } public long getMarkCalls() { return marks; } /** * Set event count to max of existing and new. * * @param which * @param ev * @return */ public synchronized long maxEvents(int which, long ev) { counts[which].set(Math.max(counts[which].get(), ev)); return counts[which].get(); } public long maxEvents(Enum which, long ev) { return maxEvents(which.ordinal(), ev); } /** * Add X events to the event count. * * @param which * @param ev * @return */ public long addEvents(int which, long ev) { return counts[which].getAndAdd(ev); } public long addEvents(Enum which, long ev) { return addEvents(which.ordinal(), ev); } public synchronized long deltaEvents(int which, long ev) { rates[which] = -1; long ret = ev - counts[which].get(); counts[which].set(ev); return ret; } public long deltaEvents(Enum which, long ev) { return deltaEvents(which.ordinal(), ev); } /** * Returns the number of events per second since the last mark. * Resets the event counter; * * @return events per time period for the first tracked item */ public synchronized long mark() { long time = System.currentTimeMillis(); for (int i = 0; i < names.length; i++) { if (rates[i] >= 0) { rates[i] = (counts[i].get() * rate) / (time - mark + 1); counts[i].set(0); } } mark = time; marks++; return rates[0]; } public long getLastTime() { return mark; } public long getEventCount(int which) { return counts[which].get(); } public long getEventCount(Enum which) { return getEventCount(which.ordinal()); } public long getEventRate(int which) { assert (which >= 0 && which < names.length); return rates[which]; } public long getEventRate(Enum which) { return getEventRate(which.ordinal()); } public long getPeriodRemaining() { return (mark + rate) - System.currentTimeMillis(); } public boolean periodHasElapsed() { return hasElapsed(rate); } public boolean hasElapsed(long time) { return sinceLastMark() >= time; } public long sinceLastMark() { return System.currentTimeMillis() - mark; } }