[r=Peter.Gromov]

- customizable sleeping policy for output reading polling loop
- for file watcher use adaptive increasing sleep delay on idling
This commit is contained in:
Maxim.Mossienko
2013-01-22 18:59:01 +01:00
parent 7b1b3364d5
commit c87245fdfb
4 changed files with 65 additions and 27 deletions
@@ -343,6 +343,10 @@ public class FileWatcher {
myWriter.newLine();
myWriter.flush();
}
protected boolean useAdaptiveSleepingPolicyWhenReadingOutput() {
return true;
}
}
public boolean isWatched(@NotNull final VirtualFile file) {
@@ -26,6 +26,8 @@ import java.io.*;
import java.nio.charset.Charset;
import java.util.concurrent.*;
import static com.intellij.util.io.BaseOutputReader.AdaptiveSleepingPolicy;
public class BaseOSProcessHandler extends ProcessHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.OSProcessHandlerBase");
@@ -55,6 +57,8 @@ public class BaseOSProcessHandler extends ProcessHandler {
return myProcess;
}
protected boolean useAdaptiveSleepingPolicyWhenReadingOutput() { return false; }
@Override
public void startNotify() {
if (myCommandLine != null) {
@@ -65,8 +69,10 @@ public class BaseOSProcessHandler extends ProcessHandler {
@Override
public void startNotified(final ProcessEvent event) {
try {
final BaseOutputReader stdoutReader = new SimpleOutputReader(createProcessOutReader(), ProcessOutputTypes.STDOUT);
final BaseOutputReader stderrReader = new SimpleOutputReader(createProcessErrReader(), ProcessOutputTypes.STDERR);
BaseOutputReader.SleepingPolicy adaptiveSleepingPolicy =
useAdaptiveSleepingPolicyWhenReadingOutput() ? new AdaptiveSleepingPolicy() : AdaptiveSleepingPolicy.SIMPLE;
final BaseOutputReader stdoutReader = new SimpleOutputReader(createProcessOutReader(), ProcessOutputTypes.STDOUT, adaptiveSleepingPolicy);
final BaseOutputReader stderrReader = new SimpleOutputReader(createProcessErrReader(), ProcessOutputTypes.STDERR, adaptiveSleepingPolicy);
myWaitFor.setTerminationCallback(new Consumer<Integer>() {
@Override
@@ -239,8 +245,8 @@ public class BaseOSProcessHandler extends ProcessHandler {
private final Key myProcessOutputType;
private SimpleOutputReader(@NotNull Reader reader, @NotNull Key processOutputType) {
super(reader);
private SimpleOutputReader(@NotNull Reader reader, @NotNull Key processOutputType, SleepingPolicy sleepingPolicy) {
super(reader, sleepingPolicy);
myProcessOutputType = processOutputType;
start();
}
@@ -1,3 +1,4 @@
/*
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
@@ -38,9 +39,15 @@ public abstract class BaseOutputReader {
private boolean skipLF = false;
private Future<?> myFinishedFuture = null;
protected final @NotNull SleepingPolicy mySleepingPolicy;
public BaseOutputReader(@NotNull Reader reader) {
this(reader, null);
}
public BaseOutputReader(@NotNull Reader reader, SleepingPolicy sleepingPolicy) {
myReader = reader;
mySleepingPolicy = sleepingPolicy != null ? sleepingPolicy: SleepingPolicy.SIMPLE;
}
protected void start() {
@@ -55,15 +62,50 @@ public abstract class BaseOutputReader {
protected abstract Future<?> executeOnPooledThread(Runnable runnable);
public interface SleepingPolicy {
int sleepTimeWhenWasActive = 1;
int sleepTimeWhenIdle = 5;
SleepingPolicy SIMPLE = new SleepingPolicy() {
@Override
public int getTimeToSleep(boolean wasActive) {
return wasActive ? sleepTimeWhenWasActive : sleepTimeWhenIdle;
}
};
int getTimeToSleep(boolean wasActive);
}
public static class AdaptiveSleepingPolicy implements SleepingPolicy {
private final static int maxSleepTimeWhenIdle = 200;
private final static int maxIterationsWithCurrentSleepTime = 50;
private volatile int myIterationsWithCurrentTime;
private volatile int myCurrentSleepTime = sleepTimeWhenIdle;
@Override
public int getTimeToSleep(boolean wasActive) {
int currentSleepTime = myCurrentSleepTime; // volatile read
if (wasActive) currentSleepTime = sleepTimeWhenWasActive;
else if (currentSleepTime == sleepTimeWhenWasActive) {
currentSleepTime = sleepTimeWhenIdle;
myIterationsWithCurrentTime = 0;
}
else {
int iterationsWithCurrentTime = ++myIterationsWithCurrentTime;
if (iterationsWithCurrentTime >= maxIterationsWithCurrentSleepTime) {
myIterationsWithCurrentTime = 0;
currentSleepTime = Math.min(2* currentSleepTime, maxSleepTimeWhenIdle);
}
}
myCurrentSleepTime = currentSleepTime; // volatile write
return currentSleepTime;
}
}
protected void doRun() {
try {
final int sleepTimeWhenRead = 1;
final int initialSleepTimeWhenIdle = 5;
final int maxSleepTimeWhenIdle = 200;
final int maxIterationsWithCurrentSleepTime = 50;
int iterationsWithCurrentTime = 0;
int currentSleepTime = initialSleepTimeWhenIdle;
while (true) {
boolean read = readAvailable();
@@ -71,21 +113,7 @@ public abstract class BaseOutputReader {
break;
}
// give other threads a chance
if (read) currentSleepTime = sleepTimeWhenRead;
else if (currentSleepTime == sleepTimeWhenRead) {
currentSleepTime = initialSleepTimeWhenIdle;
iterationsWithCurrentTime = 0;
}
else {
++iterationsWithCurrentTime;
if (iterationsWithCurrentTime == maxIterationsWithCurrentSleepTime) {
iterationsWithCurrentTime = 0;
currentSleepTime = Math.min(2* currentSleepTime, maxSleepTimeWhenIdle);
}
}
TimeoutUtil.sleep(currentSleepTime);
TimeoutUtil.sleep(mySleepingPolicy.getTimeToSleep(read));
}
}
catch (IOException e) {
@@ -46,7 +46,7 @@ public abstract class OutputReader extends BaseOutputReader {
break;
}
Thread.sleep(read ? 1 : 5); // give other threads a chance
Thread.sleep(mySleepingPolicy.getTimeToSleep(read));
}
}
catch (InterruptedException ignore) {