/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.util;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
public class StopWatch {
private long start;
private long end;
private Map<String, TimeSlice> markerMap;
public StopWatch() {
reset();
}
public void markTimeBegin(String marker) {
if (markerMap.containsKey(marker)) {
TimeSlice ts = (TimeSlice) markerMap.get(marker);
ts.cont();
} else {
markerMap.put(marker, new TimeSlice(marker));
}
}
public void markTimeEnd(String marker) {
if (!markerMap.containsKey(marker)) {
throw new IllegalArgumentException("Invalid marker");
}
TimeSlice ts = (TimeSlice) markerMap.get(marker);
ts.setFinished();
}
public StopWatch(long start) {
this.start = start;
markerMap = new HashMap<String, TimeSlice>();
}
public long reset() {
try {
return this.getElapsed();
} finally {
start = System.currentTimeMillis();
markerMap = new HashMap<String, TimeSlice>();
}
}
public long getElapsed() {
end = System.currentTimeMillis();
return end - start;
}
public String toString() {
final long elap = this.getElapsed();
final StringBuffer buf = new StringBuffer(formatMillis(elap));
if (markerMap.size() > 0) {
buf.append(" {StopWatch Markers:\n");
long totalMarked = 0;
TreeSet<String> keys = new TreeSet<String>(markerMap.keySet());
for (String key : keys) {
TimeSlice ts = markerMap.get(key);
totalMarked += (ts.end - ts.begin);
ts.writeBuf(buf);
buf.append('\n');
}
long unmarked = elap - totalMarked;
if (unmarked > 99) { // only show if the value is substantial
buf.append(" [unmarked=").append(formatMillis(unmarked)).append("]\n");
}
buf.append("}");
}
return buf.toString();
}
private String formatMillis(long millis) {
final String fraction = String.valueOf(millis % 1000L);
int pad = 3 - fraction.length();
final StringBuffer buf = new StringBuffer().append(millis / 1000L).append('.');
// for example, 15 millseconds formatted as ".015" rather than ".15"
while (pad-- > 0) {
buf.append("0");
}
buf.append(fraction).append(" secs");
return buf.toString();
}
class TimeSlice {
String marker;
long begin;
long end;
public TimeSlice(String marker) {
this.marker = marker;
this.begin = this.end = System.currentTimeMillis();
}
public void setFinished() {
this.end = System.currentTimeMillis();
}
public void cont() {
begin -= (end - begin);
}
public void writeBuf(StringBuffer buf) {
long elap = end - begin;
buf.append(" [").append(marker).append("=").append(formatMillis(elap)).append("] ");
}
}
}