|
@@ -28,6 +28,7 @@ import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
import org.apache.hadoop.conf.Configuration;
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
|
+import org.apache.hadoop.service.AbstractService;
|
|
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.base.Preconditions;
|
|
@@ -43,21 +44,21 @@ import com.google.common.collect.Sets;
|
|
* detected, the thread logs a message.
|
|
* detected, the thread logs a message.
|
|
*/
|
|
*/
|
|
@InterfaceAudience.Private
|
|
@InterfaceAudience.Private
|
|
-public class JvmPauseMonitor {
|
|
|
|
|
|
+public class JvmPauseMonitor extends AbstractService {
|
|
private static final Log LOG = LogFactory.getLog(
|
|
private static final Log LOG = LogFactory.getLog(
|
|
JvmPauseMonitor.class);
|
|
JvmPauseMonitor.class);
|
|
|
|
|
|
/** The target sleep time */
|
|
/** The target sleep time */
|
|
private static final long SLEEP_INTERVAL_MS = 500;
|
|
private static final long SLEEP_INTERVAL_MS = 500;
|
|
-
|
|
|
|
|
|
+
|
|
/** log WARN if we detect a pause longer than this threshold */
|
|
/** log WARN if we detect a pause longer than this threshold */
|
|
- private final long warnThresholdMs;
|
|
|
|
|
|
+ private long warnThresholdMs;
|
|
private static final String WARN_THRESHOLD_KEY =
|
|
private static final String WARN_THRESHOLD_KEY =
|
|
"jvm.pause.warn-threshold.ms";
|
|
"jvm.pause.warn-threshold.ms";
|
|
private static final long WARN_THRESHOLD_DEFAULT = 10000;
|
|
private static final long WARN_THRESHOLD_DEFAULT = 10000;
|
|
-
|
|
|
|
|
|
+
|
|
/** log INFO if we detect a pause longer than this threshold */
|
|
/** log INFO if we detect a pause longer than this threshold */
|
|
- private final long infoThresholdMs;
|
|
|
|
|
|
+ private long infoThresholdMs;
|
|
private static final String INFO_THRESHOLD_KEY =
|
|
private static final String INFO_THRESHOLD_KEY =
|
|
"jvm.pause.info-threshold.ms";
|
|
"jvm.pause.info-threshold.ms";
|
|
private static final long INFO_THRESHOLD_DEFAULT = 1000;
|
|
private static final long INFO_THRESHOLD_DEFAULT = 1000;
|
|
@@ -65,29 +66,32 @@ public class JvmPauseMonitor {
|
|
private long numGcWarnThresholdExceeded = 0;
|
|
private long numGcWarnThresholdExceeded = 0;
|
|
private long numGcInfoThresholdExceeded = 0;
|
|
private long numGcInfoThresholdExceeded = 0;
|
|
private long totalGcExtraSleepTime = 0;
|
|
private long totalGcExtraSleepTime = 0;
|
|
-
|
|
|
|
|
|
+
|
|
private Thread monitorThread;
|
|
private Thread monitorThread;
|
|
private volatile boolean shouldRun = true;
|
|
private volatile boolean shouldRun = true;
|
|
|
|
|
|
- public JvmPauseMonitor(Configuration conf) {
|
|
|
|
|
|
+ public JvmPauseMonitor() {
|
|
|
|
+ super(JvmPauseMonitor.class.getName());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void serviceInit(Configuration conf) throws Exception {
|
|
this.warnThresholdMs = conf.getLong(WARN_THRESHOLD_KEY, WARN_THRESHOLD_DEFAULT);
|
|
this.warnThresholdMs = conf.getLong(WARN_THRESHOLD_KEY, WARN_THRESHOLD_DEFAULT);
|
|
this.infoThresholdMs = conf.getLong(INFO_THRESHOLD_KEY, INFO_THRESHOLD_DEFAULT);
|
|
this.infoThresholdMs = conf.getLong(INFO_THRESHOLD_KEY, INFO_THRESHOLD_DEFAULT);
|
|
|
|
+ super.serviceInit(conf);
|
|
}
|
|
}
|
|
-
|
|
|
|
- public void start() {
|
|
|
|
- Preconditions.checkState(monitorThread == null,
|
|
|
|
- "Already started");
|
|
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void serviceStart() throws Exception {
|
|
monitorThread = new Daemon(new Monitor());
|
|
monitorThread = new Daemon(new Monitor());
|
|
- if (shouldRun) {
|
|
|
|
- monitorThread.start();
|
|
|
|
- } else {
|
|
|
|
- LOG.warn("stop() was called before start() completed");
|
|
|
|
- }
|
|
|
|
|
|
+ monitorThread.start();
|
|
|
|
+ super.serviceStart();
|
|
}
|
|
}
|
|
-
|
|
|
|
- public void stop() {
|
|
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void serviceStop() throws Exception {
|
|
shouldRun = false;
|
|
shouldRun = false;
|
|
- if (isStarted()) {
|
|
|
|
|
|
+ if (monitorThread != null) {
|
|
monitorThread.interrupt();
|
|
monitorThread.interrupt();
|
|
try {
|
|
try {
|
|
monitorThread.join();
|
|
monitorThread.join();
|
|
@@ -95,12 +99,13 @@ public class JvmPauseMonitor {
|
|
Thread.currentThread().interrupt();
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ super.serviceStop();
|
|
}
|
|
}
|
|
|
|
|
|
public boolean isStarted() {
|
|
public boolean isStarted() {
|
|
return monitorThread != null;
|
|
return monitorThread != null;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
public long getNumGcWarnThreadholdExceeded() {
|
|
public long getNumGcWarnThreadholdExceeded() {
|
|
return numGcWarnThresholdExceeded;
|
|
return numGcWarnThresholdExceeded;
|
|
}
|
|
}
|
|
@@ -212,8 +217,11 @@ public class JvmPauseMonitor {
|
|
* with a 1GB heap will very quickly go into "GC hell" and result in
|
|
* with a 1GB heap will very quickly go into "GC hell" and result in
|
|
* log messages about the GC pauses.
|
|
* log messages about the GC pauses.
|
|
*/
|
|
*/
|
|
|
|
+ @SuppressWarnings("resource")
|
|
public static void main(String []args) throws Exception {
|
|
public static void main(String []args) throws Exception {
|
|
- new JvmPauseMonitor(new Configuration()).start();
|
|
|
|
|
|
+ JvmPauseMonitor monitor = new JvmPauseMonitor();
|
|
|
|
+ monitor.init(new Configuration());
|
|
|
|
+ monitor.start();
|
|
List<String> list = Lists.newArrayList();
|
|
List<String> list = Lists.newArrayList();
|
|
int i = 0;
|
|
int i = 0;
|
|
while (true) {
|
|
while (true) {
|