diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index d23536467b56..1b5a91c359ff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -343,6 +343,10 @@ public class FileWatcher { myWriter.newLine(); myWriter.flush(); } + + protected boolean useAdaptiveSleepingPolicyWhenReadingOutput() { + return true; + } } public boolean isWatched(@NotNull final VirtualFile file) { diff --git a/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java b/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java index b73d5e732be5..f9ca8c45599e 100644 --- a/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java +++ b/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java @@ -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() { @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(); } diff --git a/platform/util/src/com/intellij/util/io/BaseOutputReader.java b/platform/util/src/com/intellij/util/io/BaseOutputReader.java index 8f62efa44774..ead3ee5050dd 100644 --- a/platform/util/src/com/intellij/util/io/BaseOutputReader.java +++ b/platform/util/src/com/intellij/util/io/BaseOutputReader.java @@ -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) { diff --git a/platform/util/src/com/intellij/util/io/OutputReader.java b/platform/util/src/com/intellij/util/io/OutputReader.java index 88d41b943581..489e6f51b645 100644 --- a/platform/util/src/com/intellij/util/io/OutputReader.java +++ b/platform/util/src/com/intellij/util/io/OutputReader.java @@ -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) {