/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* 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.intellij.util;
import com.intellij.util.containers.UnsignedShortArrayList;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
public class PausesStat {
private static final int N_MAX = 100000;
// stores durations of the event: (timestamp of the event end) - (timestamp of the event start) in milliseconds.
private final UnsignedShortArrayList durations = new UnsignedShortArrayList();
@NotNull private final String myName;
private final Thread myEdtThread;
private boolean started;
private long startTimeStamp;
private int maxDuration;
private Object maxDurationDescription;
private int totalNumberRecorded;
private int indexToOverwrite; // used when pauses.size() == N_MAX and we have to overflow cyclically
public PausesStat(@NotNull String name) {
myName = name;
assert EventQueue.isDispatchThread() : Thread.currentThread();
myEdtThread = Thread.currentThread();
}
private int register(int duration) {
if (durations.size() == N_MAX) {
durations.set(indexToOverwrite, duration);
indexToOverwrite = (indexToOverwrite + 1) % N_MAX;
}
else {
durations.add(duration);
}
return duration;
}
public void started() {
assertEdt();
assert !started;
started = true;
startTimeStamp = System.currentTimeMillis();
}
private void assertEdt() {
assert Thread.currentThread() == myEdtThread : Thread.currentThread();
}
public void finished(@NotNull String description) {
assertEdt();
assert started;
long finishStamp = System.currentTimeMillis();
int duration = (int)(finishStamp - startTimeStamp);
started = false;
duration = Math.min(duration, (1 << 16) - 1);
if (duration > maxDuration) {
maxDuration = duration;
maxDurationDescription = description;
}
totalNumberRecorded++;
register(duration);
}
public String statistics() {
int number = durations.size();
int[] duration = durations.toArray();
int total = 0;
for (int d : duration) {
total += d;
}
return myName + " Statistics" + (totalNumberRecorded == number ? "" : " ("+totalNumberRecorded+" events was recorded in total, but only last "+number+" are reported here)")+":"+
"\nEvent number: " + number +
"\nTotal time spent: " + total + "ms" +
"\nAverage duration: " + (number == 0 ? 0 : total / number) + "ms" +
"\nMedian duration: " + ArrayUtil.averageAmongMedians(duration, 3) + "ms" +
"\nMax duration: " + (maxDuration == 65535 ? ">" : "") + maxDuration+ "ms (it was '"+maxDurationDescription+"')";
}
}