less memory for action update/write action statistics

This commit is contained in:
Alexey Kudravtsev
2016-07-18 12:57:21 +03:00
parent 071319f47a
commit 22b9b89f2b
5 changed files with 262 additions and 31 deletions
@@ -88,7 +88,6 @@ public class ActionUtil {
+ " not available while " + ApplicationNamesInfo.getInstance().getProductName() + " is updating indices";
}
public static final PausesStat ACTION_UPDATE_PAUSES = new PausesStat("AnAction.update()");
private static int insidePerformDumbAwareUpdate;
/**
* @param action action
@@ -113,7 +112,7 @@ public class ActionUtil {
final boolean notAllowed = dumbMode && !action.isDumbAware();
if (insidePerformDumbAwareUpdate++ == 0) {
ACTION_UPDATE_PAUSES.started();
ActionPauses.STAT.started();
}
try {
if (beforeActionPerformed) {
@@ -133,7 +132,7 @@ public class ActionUtil {
}
finally {
if (--insidePerformDumbAwareUpdate == 0) {
ACTION_UPDATE_PAUSES.finished(presentation.getText()+" action update ("+action.getClass()+")");
ActionPauses.STAT.finished(presentation.getText() + " action update (" + action.getClass() + ")");
}
if (notAllowed) {
if (wasEnabledBefore == null) {
@@ -145,6 +144,9 @@ public class ActionUtil {
return false;
}
public static class ActionPauses {
public static final PausesStat STAT = new PausesStat("AnAction.update()");
}
/**
* @return whether a dumb mode is in progress for the passed project or, if the argument is null, for any open project.
@@ -488,7 +488,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
if (gatherStatistics) {
//noinspection TestOnlyProblems
LOG.info(writeActionStatistics());
LOG.info(ActionUtil.ACTION_UPDATE_PAUSES.statistics());
LOG.info(ActionUtil.ActionPauses.STAT.statistics());
//noinspection TestOnlyProblems
LOG.info(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics()
+ "; ProcessIOExecutorService threads: "+((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter()
@@ -54,7 +54,7 @@ public class _LastInSuiteTest extends TestCase {
PlatformTestUtil.cleanupAllProjects();
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
System.out.println(application.writeActionStatistics());
System.out.println(ActionUtil.ACTION_UPDATE_PAUSES.statistics());
System.out.println(ActionUtil.ActionPauses.STAT.statistics());
System.out.println(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics());
System.out.println("ProcessIOExecutorService threads created: "+((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter());
@@ -15,16 +15,19 @@
*/
package com.intellij.util;
import gnu.trove.TIntArrayList;
import com.intellij.util.containers.UnsignedShortArrayList;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
public class PausesStat {
private static final int N_MAX = 200000;
// stores pairs of (timestamp of the event start), (timestamp of the event end). Timestamps are stored as diffs between System.currentTimeMillis() and epochStart.
private final TIntArrayList pauses = new TIntArrayList();
private final long epochStart;
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 volatile boolean started;
private final Thread myEdtThread;
private boolean started;
private long startTimeStamp;
private int maxDuration;
private Object maxDurationDescription;
private int totalNumberRecorded;
@@ -32,51 +35,51 @@ public class PausesStat {
public PausesStat(@NotNull String name) {
myName = name;
epochStart = System.currentTimeMillis();
assert EventQueue.isDispatchThread() : Thread.currentThread();
myEdtThread = Thread.currentThread();
}
private int register() {
int stamp = (int)(System.currentTimeMillis() - epochStart);
if (pauses.size()/2 == N_MAX) {
pauses.set(indexToOverwrite, stamp);
private int register(int duration) {
if (durations.size() == N_MAX) {
durations.set(indexToOverwrite, duration);
indexToOverwrite = (indexToOverwrite + 1) % N_MAX;
}
else {
pauses.add(stamp);
durations.add(duration);
}
return stamp;
return duration;
}
public void started() {
assertEdt();
assert !started;
register();
started = true;
startTimeStamp = System.currentTimeMillis();
}
private void assertEdt() {
assert Thread.currentThread() == myEdtThread : Thread.currentThread();
}
public void finished(@NotNull String description) {
assertEdt();
assert started;
int startStamp = pauses.get(pauses.size()/2 == N_MAX ? indexToOverwrite-1 : pauses.size() - 1);
int finishStamp = register();
int duration = finishStamp - startStamp;
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 total = 0;
int number = pauses.size() / 2;
int[] duration = new int[number];
for (int i = 0; i < number*2; i+=2) {
int start = pauses.get(i);
int finish = pauses.get(i+1);
int thisDuration = finish - start;
total += thisDuration;
duration[i / 2] = thisDuration;
}
int number = durations.size();
int[] duration = durations.toArray();
return myName + " Statistics" + (totalNumberRecorded == number ? "" : " ("+totalNumberRecorded+" events was recorded in total, but only last "+number+" are reported here)")+":"+
"\nEvent number: " + number +
@@ -0,0 +1,226 @@
/*
* Copyright 2000-2016 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.containers;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class UnsignedShortArrayList implements Cloneable {
private char[] myData; // use char as an unsigned short
private int mySize;
public UnsignedShortArrayList(int initialCapacity) {
myData = new char[initialCapacity];
}
public UnsignedShortArrayList() {
this(10);
}
public void trimToSize() {
if (mySize < myData.length){
myData = ArrayUtil.realloc(myData, mySize);
}
}
public void ensureCapacity(int minCapacity) {
int oldCapacity = myData.length;
if (minCapacity > oldCapacity){
char[] oldData = myData;
int newCapacity = oldCapacity * 3 / 2 + 1;
if (newCapacity < minCapacity){
newCapacity = minCapacity;
}
myData = new char[newCapacity];
System.arraycopy(oldData, 0, myData, 0, mySize);
}
}
public void fill(int fromIndex, int toIndex, int value) {
assertShort(value);
if (toIndex > mySize) {
ensureCapacity(toIndex);
mySize = toIndex;
}
Arrays.fill(myData, fromIndex, toIndex, (char)value);
}
public int size() {
return mySize;
}
public boolean isEmpty() {
return mySize == 0;
}
public boolean contains(int element) {
assertShort(element);
return indexOf(element) >= 0;
}
public int indexOf(int element) {
assertShort(element);
return indexOf(element, 0, mySize);
}
public int indexOf(int element, int startIndex, int endIndex) {
assertShort(element);
if (startIndex < 0 || endIndex < startIndex || endIndex > mySize) {
throw new IndexOutOfBoundsException("startIndex: "+startIndex+"; endIndex: "+endIndex+"; mySize: "+mySize);
}
for(int i = startIndex; i < endIndex; i++){
if (element == myData[i]) return i;
}
return -1;
}
public int lastIndexOf(int element) {
assertShort(element);
for(int i = mySize - 1; i >= 0; i--){
if (element == myData[i]) return i;
}
return -1;
}
@Override
public Object clone() {
try{
UnsignedShortArrayList v = (UnsignedShortArrayList)super.clone();
v.myData = myData.clone();
return v;
}
catch(CloneNotSupportedException e){
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
@NotNull
public int[] toArray() {
return toArray(0,mySize);
}
@NotNull
public int[] toArray(@NotNull int[] a) {
if (a.length < mySize){
a = new int[mySize];
}
for (int i = 0; i < mySize; i++) {
char c = myData[i];
a[i] = c;
}
return a;
}
@NotNull
public int[] toArray(int startIndex, int length) {
int[] result = new int[length];
for (int i = startIndex; i < length; i++) {
char c = myData[i];
result[i-startIndex] = c;
}
return result;
}
public int get(int index) {
checkRange(index);
return myData[index];
}
public int getQuick(int index) {
return myData[index];
}
public int set(int index, int element) {
checkRange(index);
int oldValue = myData[index];
setQuick(index, element);
return oldValue;
}
public void setQuick(int index, int element) {
assertShort(element);
myData[index] = (char)element;
}
private static void assertShort(int element) {
assert element >= 0 && element < 1<<16 : element;
}
public void add(int element) {
ensureCapacity(mySize + 1);
setQuick(mySize++, element);
}
public void add(int index, int element) {
if (index > mySize || index < 0){
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
ensureCapacity(mySize + 1);
System.arraycopy(myData, index, myData, index + 1, mySize - index);
setQuick(index, element);
mySize++;
}
public int remove(int index) {
checkRange(index);
int oldValue = myData[index];
int numMoved = mySize - index - 1;
if (numMoved > 0){
System.arraycopy(myData, index + 1, myData, index,numMoved);
}
mySize--;
return oldValue;
}
public void clear() {
mySize = 0;
}
public void removeRange(int fromIndex, int toIndex) {
int numMoved = mySize - toIndex;
System.arraycopy(myData, toIndex, myData, fromIndex, numMoved);
mySize -= toIndex - fromIndex;
}
public void copyRange(int fromIndex, int length, int toIndex) {
if (length < 0 || fromIndex < 0 || fromIndex + length > mySize || toIndex < 0 || toIndex + length > mySize) {
throw new IndexOutOfBoundsException("fromIndex: "+fromIndex+"; length: "+length+"; toIndex: "+toIndex+"; mySize: "+mySize);
}
System.arraycopy(myData, fromIndex, myData, toIndex, length);
}
private void checkRange(int index) {
if (index >= mySize || index < 0){
//noinspection HardCodedStringLiteral
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
}
@Override
public String toString() {
return Arrays.toString(toArray());
}
}