You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2019/04/23 01:33:19 UTC
[maven-surefire] branch docker updated: resilient to GC pauses 75%
(22.5 seconds) of the ping checker period (30 seconds)
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch docker
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
The following commit(s) were added to refs/heads/docker by this push:
new a61de73 resilient to GC pauses 75% (22.5 seconds) of the ping checker period (30 seconds)
a61de73 is described below
commit a61de735ed381331049d163b03ddaed425064077
Author: tibordigana <ti...@apache.org>
AuthorDate: Tue Apr 23 03:33:05 2019 +0200
resilient to GC pauses 75% (22.5 seconds) of the ping checker period (30 seconds)
---
.../apache/maven/surefire/booter/ForkedBooter.java | 63 +++++++++++-----------
1 file changed, 30 insertions(+), 33 deletions(-)
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index b0a75b5..1c3c1ac 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -29,6 +29,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlException;
@@ -39,7 +40,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Math.max;
import static java.lang.Thread.currentThread;
@@ -48,6 +48,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.maven.surefire.booter.SystemPropertyManager.setSystemProperties;
import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg;
import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+import static org.apache.maven.surefire.util.internal.StringUtils.NL;
/**
* The part of the booter that is unique to a forked vm.
@@ -62,13 +63,11 @@ import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDae
public final class ForkedBooter
{
private static final long DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS = 30L;
- private static final long PING_HALFPERIOD_IN_SECONDS = 15L;
- private static final long PING_TIMEOUT_MAX_DELAY_IN_MILLIS = 7500L; // due to GC pauses
+ private static final long PING_TIMEOUT_IN_SECONDS = 30L;
private static final long ONE_SECOND_IN_MILLIS = 1000L;
- private static final long PING_MAX_TIMEOUT_IN_MILLIS =
- PING_HALFPERIOD_IN_SECONDS * ONE_SECOND_IN_MILLIS + PING_TIMEOUT_MAX_DELAY_IN_MILLIS;
private static final String LAST_DITCH_SHUTDOWN_THREAD = "surefire-forkedjvm-last-ditch-daemon-shutdown-thread-";
private static final String PING_THREAD = "surefire-forkedjvm-ping-";
+ private static final double GC_FACTOR = 0.75d;
private final CommandReader commandReader = CommandReader.getReader();
private final ForkedChannelEncoder eventChannel = new ForkedChannelEncoder( System.out );
@@ -190,7 +189,7 @@ public final class ForkedBooter
pingMechanisms.pingScheduler.scheduleWithFixedDelay( checkerJob, 0L, 1L, SECONDS );
}
Runnable pingJob = createPingJob( pingPeriod, pingMechanisms.pluginProcessChecker );
- pingMechanisms.pingScheduler.scheduleWithFixedDelay( pingJob, 0L, PING_HALFPERIOD_IN_SECONDS, SECONDS );
+ pingMechanisms.pingScheduler.scheduleWithFixedDelay( pingJob, 0L, PING_TIMEOUT_IN_SECONDS, SECONDS );
return pingMechanisms;
}
@@ -270,26 +269,17 @@ public final class ForkedBooter
{
if ( !canUseNewPingMechanism( pluginProcessChecker ) )
{
- int periodCounter = pingPeriod.pingTimeoutCounter.getAndIncrement();
- if ( periodCounter % 2 == 0 )
+ final long lastGcPeriod = pingPeriod.lastGcPeriod();
+ final boolean longGcPausesDetected = lastGcPeriod > GC_FACTOR * PING_TIMEOUT_IN_SECONDS;
+ final boolean hasPing = pingPeriod.pingDone.getAndSet( false );
+ if ( !longGcPausesDetected && hasPing )
{
- boolean longGcPausesDetected = pingPeriod.firstHalfPeriod >= PING_MAX_TIMEOUT_IN_MILLIS;
- pingPeriod.periodStartTime = System.currentTimeMillis();
- longGcPausesDetected |=
- pingPeriod.periodStartTime - pingPeriod.halfPeriodTime >= PING_MAX_TIMEOUT_IN_MILLIS;
- boolean hasPing = pingPeriod.pingDone.getAndSet( false );
- if ( !longGcPausesDetected && hasPing )
- {
- DumpErrorSingleton.getSingleton()
- .dumpText( "Killing self fork JVM. PING timeout elapsed." );
-
- kill();
- }
- }
- else
- {
- pingPeriod.halfPeriodTime = System.currentTimeMillis();
- pingPeriod.firstHalfPeriod = pingPeriod.halfPeriodTime - pingPeriod.periodStartTime;
+ DumpErrorSingleton.getSingleton()
+ .dumpText( "Killing self fork JVM. PING timeout elapsed."
+ + NL
+ + "lastGcPeriod = " + lastGcPeriod + " millis" );
+
+ kill();
}
}
}
@@ -441,7 +431,7 @@ public final class ForkedBooter
private static ScheduledExecutorService createPingScheduler()
{
- ThreadFactory threadFactory = newDaemonThreadFactory( PING_THREAD + PING_HALFPERIOD_IN_SECONDS + "s" );
+ ThreadFactory threadFactory = newDaemonThreadFactory( PING_THREAD + PING_TIMEOUT_IN_SECONDS + "s" );
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1, threadFactory );
executor.setKeepAliveTime( 3L, SECONDS );
executor.setMaximumPoolSize( 2 );
@@ -495,17 +485,24 @@ public final class ForkedBooter
private static class PingPeriod
{
- private final AtomicInteger pingTimeoutCounter = new AtomicInteger();
private final AtomicBoolean pingDone = new AtomicBoolean();
- private volatile long halfPeriodTime;
- private volatile long periodStartTime;
- private volatile long firstHalfPeriod;
+ private volatile long accumulatedCollectionElapsedTime;
private PingPeriod()
{
- long now = System.currentTimeMillis();
- periodStartTime = now;
- halfPeriodTime = now;
+ lastGcPeriod();
+ }
+
+ private long lastGcPeriod()
+ {
+ final long lastAccumulatedGcTime = accumulatedCollectionElapsedTime;
+ long currentAccumulatedGcTime = 0L;
+ for ( GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans() )
+ {
+ currentAccumulatedGcTime = max( currentAccumulatedGcTime, gc.getCollectionTime() );
+ }
+ accumulatedCollectionElapsedTime = currentAccumulatedGcTime;
+ return currentAccumulatedGcTime - lastAccumulatedGcTime;
}
}
}