This commit is contained in:
Marcus Larsson 2016-03-21 11:42:47 +01:00
commit 85ba16be9d
23 changed files with 207 additions and 170 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,6 +36,7 @@
#include "compiler/compileLog.hpp"
#include "compiler/compilerDirectives.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/timerTrace.hpp"
typedef enum {
_t_compile,

View File

@ -32,6 +32,7 @@
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_ValueStack.hpp"
#include "code/vmreg.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "utilities/bitMap.inline.hpp"
#ifndef PRODUCT

View File

@ -49,6 +49,7 @@
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/sweeper.hpp"
#include "runtime/timerTrace.hpp"
#include "trace/tracing.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "utilities/bitMap.inline.hpp"
// The MethodLiveness class performs a simple liveness analysis on a method

View File

@ -33,7 +33,6 @@
#include "memory/universe.hpp"
#include "prims/jni_md.h"
#include "utilities/ticks.hpp"
#include "runtime/timer.hpp"
#define LOG_STOP_TIME_FORMAT "(%.3fs, %.3fs) %.3fms"
#define LOG_STOP_HEAP_FORMAT SIZE_FORMAT "M->" SIZE_FORMAT "M(" SIZE_FORMAT "M)"

View File

@ -27,7 +27,7 @@
#include "interpreter/cppInterpreterGenerator.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#ifdef CC_INTERP
@ -43,7 +43,7 @@ void CppInterpreter::initialize() {
// generate interpreter
{ ResourceMark rm;
TraceStartupTime timer("Interpreter generation");
TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));
int code_size = InterpreterCodeSize;
NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space
_code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL,

View File

@ -31,7 +31,7 @@
#include "interpreter/templateInterpreterGenerator.hpp"
#include "interpreter/templateTable.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#ifndef CC_INTERP
@ -49,7 +49,7 @@ void TemplateInterpreter::initialize() {
// generate interpreter
{ ResourceMark rm;
TraceStartupTime timer("Interpreter generation");
TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));
int code_size = InterpreterCodeSize;
NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space
#if INCLUDE_JVMTI

View File

@ -26,7 +26,7 @@
#include "gc/shared/collectedHeap.hpp"
#include "interpreter/interp_masm.hpp"
#include "interpreter/templateTable.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#ifdef CC_INTERP
@ -245,7 +245,7 @@ void TemplateTable::initialize() {
if (_is_initialized) return;
// Initialize table
TraceStartupTime timer("TemplateTable initialization");
TraceTime timer("TemplateTable initialization", TRACETIME_LOG(Info, startuptime));
_bs = Universe::heap()->barrier_set();

View File

@ -48,6 +48,7 @@
#include "gc/g1/heapRegion.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframe_hp.hpp"
#include "runtime/vmStructs.hpp"

View File

@ -40,7 +40,7 @@
#include "memory/metaspaceShared.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/os.hpp"
#include "runtime/signature.hpp"
#include "runtime/vmThread.hpp"
@ -772,7 +772,7 @@ void MetaspaceShared::prepare_for_dumping() {
// Preload classes from a list, populate the shared spaces and dump to a
// file.
void MetaspaceShared::preload_and_dump(TRAPS) {
{ TraceStartupTime timer("Dump Shared Spaces");
{ TraceTime timer("Dump Shared Spaces", TRACETIME_LOG(Info, startuptime));
ResourceMark rm;
char class_list_path_str[JVM_MAXPATHLEN];

View File

@ -64,11 +64,10 @@
#include "runtime/init.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vm_operations.hpp"
#include "services/memoryService.hpp"
#include "utilities/copy.hpp"
@ -627,7 +626,7 @@ jint universe_init() {
guarantee(sizeof(oop) % sizeof(HeapWord) == 0,
"oop size is not not a multiple of HeapWord size");
TraceStartupTime timer("Genesis");
TraceTime timer("Genesis", TRACETIME_LOG(Info, startuptime));
JavaClasses::compute_hard_coded_offsets();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/relocator.hpp"
#include "runtime/timerTrace.hpp"
#include "utilities/bitMap.inline.hpp"
#include "prims/methodHandles.hpp"

View File

@ -39,6 +39,7 @@
#include "opto/phase.hpp"
#include "opto/regmask.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vmThread.hpp"
#include "trace/tracing.hpp"
#include "utilities/ticks.hpp"

View File

@ -59,6 +59,7 @@
#include "runtime/reflectionUtils.hpp"
#include "runtime/signature.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vmThread.hpp"
#include "services/threadService.hpp"

View File

@ -40,7 +40,7 @@
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
@ -73,7 +73,7 @@ void MethodHandles::generate_adapters() {
assert(_adapter_code == NULL, "generate only once");
ResourceMark rm;
TraceStartupTime timer("MethodHandles adapters generation");
TraceTime timer("MethodHandles adapters generation", TRACETIME_LOG(Info, startuptime));
_adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code);

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_RUNTIME_LOG_TIMER_HPP
#define SHARE_VM_RUNTIME_LOG_TIMER_HPP
#include "logging/log.hpp"
#include "runtime/timer.hpp"
// These classes are used for tracing the execution time of a block with logging
// Usage:
// { TraceStartupTime t("block time")
// some_code();
// }
//
class TraceStartupTime : public TraceTime {
public:
TraceStartupTime(const char* s) : TraceTime(s, log_is_enabled(Info, startuptime), LogTag::_startuptime) {}
};
class TraceSafepointTime : public TraceTime {
public:
TraceSafepointTime(const char* s) : TraceTime(s, log_is_enabled(Info, safepointcleanup), LogTag::_safepointcleanup) {}
};
#endif // SHARE_VM_RUNTIME_LOG_TIMER_HPP

View File

@ -44,7 +44,6 @@
#include "runtime/deoptimization.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/osThread.hpp"
@ -55,6 +54,7 @@
#include "runtime/sweeper.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "services/runtimeService.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
@ -488,38 +488,38 @@ bool SafepointSynchronize::is_cleanup_needed() {
// Various cleaning tasks that should be done periodically at safepoints
void SafepointSynchronize::do_cleanup_tasks() {
{
TraceSafepointTime t1("deflating idle monitors");
TraceTime timer("deflating idle monitors", TRACETIME_LOG(Info, safepointcleanup));
ObjectSynchronizer::deflate_idle_monitors();
}
{
TraceSafepointTime t2("updating inline caches");
TraceTime timer("updating inline caches", TRACETIME_LOG(Info, safepointcleanup));
InlineCacheBuffer::update_inline_caches();
}
{
TraceSafepointTime t3("compilation policy safepoint handler");
TraceTime timer("compilation policy safepoint handler", TRACETIME_LOG(Info, safepointcleanup));
CompilationPolicy::policy()->do_safepoint_work();
}
{
TraceSafepointTime t4("mark nmethods");
TraceTime timer("mark nmethods", TRACETIME_LOG(Info, safepointcleanup));
NMethodSweeper::mark_active_nmethods();
}
if (SymbolTable::needs_rehashing()) {
TraceSafepointTime t5("rehashing symbol table");
TraceTime timer("rehashing symbol table", TRACETIME_LOG(Info, safepointcleanup));
SymbolTable::rehash_table();
}
if (StringTable::needs_rehashing()) {
TraceSafepointTime t6("rehashing string table");
TraceTime timer("rehashing string table", TRACETIME_LOG(Info, safepointcleanup));
StringTable::rehash_table();
}
{
// CMS delays purging the CLDG until the beginning of the next safepoint and to
// make sure concurrent sweep is done
TraceSafepointTime t7("purging class loader data graph");
TraceTime timer("purging class loader data graph", TRACETIME_LOG(Info, safepointcleanup));
ClassLoaderDataGraph::purge_if_needed();
}
}

View File

@ -28,7 +28,7 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/copy.hpp"
@ -183,7 +183,7 @@ extern void StubGenerator_generate(CodeBuffer* code, bool all); // only interfac
void StubRoutines::initialize1() {
if (_code1 == NULL) {
ResourceMark rm;
TraceStartupTime timer("StubRoutines generation 1");
TraceTime timer("StubRoutines generation 1", TRACETIME_LOG(Info, startuptime));
_code1 = BufferBlob::create("StubRoutines (1)", code_size1);
if (_code1 == NULL) {
vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)");
@ -276,7 +276,7 @@ static void test_safefetchN() {
void StubRoutines::initialize2() {
if (_code2 == NULL) {
ResourceMark rm;
TraceStartupTime timer("StubRoutines generation 2");
TraceTime timer("StubRoutines generation 2", TRACETIME_LOG(Info, startuptime));
_code2 = BufferBlob::create("StubRoutines (2)", code_size2);
if (_code2 == NULL) {
vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)");

View File

@ -68,7 +68,7 @@
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniPeriodicChecker.hpp"
#include "runtime/logTimer.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/memprofiler.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
@ -3366,7 +3366,7 @@ void Threads::threads_do(ThreadClosure* tc) {
}
void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
TraceStartupTime timer("Initialize java.lang classes");
TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime));
if (EagerXrunInit && Arguments::init_libraries_at_startup()) {
create_vm_init_libraries();
@ -3413,7 +3413,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
}
void Threads::initialize_jsr292_core_classes(TRAPS) {
TraceStartupTime timer("Initialize java.lang.invoke classes");
TraceTime timer("Initialize java.lang.invoke classes", TRACETIME_LOG(Info, startuptime));
initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK);
initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK);
@ -3484,7 +3484,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
HOTSPOT_VM_INIT_BEGIN();
// Timing (must come after argument parsing)
TraceStartupTime timer("Create VM");
TraceTime timer("Create VM", TRACETIME_LOG(Info, startuptime));
// Initialize the os module after parsing the args
jint os_init_2_result = os::init_2();
@ -3573,7 +3573,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
JvmtiExport::transition_pending_onload_raw_monitors();
// Create the VMThread
{ TraceStartupTime timer("Start VMThread");
{ TraceTime timer("Start VMThread", TRACETIME_LOG(Info, startuptime));
VMThread::create();
Thread* vmthread = VMThread::vm_thread();

View File

@ -114,57 +114,6 @@ jlong TimeStamp::ticks_since_update() const {
return os::elapsed_counter() - _counter;
}
TraceTime::TraceTime(const char* title,
bool doit,
LogTagType tag) {
_active = doit;
_verbose = true;
_tag = tag;
_title = title;
if (_active) {
_accum = NULL;
_t.start();
}
}
TraceTime::TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit,
bool verbose,
LogTagType tag) {
_active = doit;
_verbose = verbose;
_tag = tag;
_title = title;
if (_active) {
_accum = accumulator;
_t.start();
}
}
TraceTime::~TraceTime() {
if (_active) {
_t.stop();
if (_accum!=NULL) _accum->add(_t);
if (_verbose) {
switch (_tag) {
case LogTag::_startuptime :
log_info(startuptime)("%s, %3.7f secs", _title, _t.seconds());
break;
case LogTag::_safepointcleanup :
log_info(safepointcleanup)("%s, %3.7f secs", _title, _t.seconds());
break;
case LogTag::__NO_TAG :
default :
tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds());
tty->flush();
}
}
}
}
TraceCPUTime::TraceCPUTime(bool doit,
bool print_cr,
outputStream *logfile) :
@ -219,3 +168,4 @@ TraceCPUTime::~TraceCPUTime() {
_logfile->flush();
}
}

View File

@ -25,7 +25,6 @@
#ifndef SHARE_VM_RUNTIME_TIMER_HPP
#define SHARE_VM_RUNTIME_TIMER_HPP
#include "logging/logTag.hpp"
#include "utilities/globalDefinitions.hpp"
// Timers for simple measurement.
@ -73,43 +72,6 @@ class TimeStamp VALUE_OBJ_CLASS_SPEC {
jlong ticks_since_update() const;
};
// TraceTime is used for tracing the execution time of a block
// Usage:
// { TraceTime t("block time")
// some_code();
// }
//
class TraceTime: public StackObj {
private:
bool _active; // do timing
bool _verbose; // report every timing
elapsedTimer _t; // timer
elapsedTimer* _accum; // accumulator
const char* _title; // name of timer
LogTagType _tag; // stream to print to
public:
// Constructors
TraceTime(const char* title,
bool doit = true,
LogTagType tag = LogTag::__NO_TAG);
TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit = true,
bool verbose = false,
LogTagType tag = LogTag::__NO_TAG);
~TraceTime();
// Accessors
void set_verbose(bool verbose) { _verbose = verbose; }
bool verbose() const { return _verbose; }
// Activation
void suspend() { if (_active) _t.stop(); }
void resume() { if (_active) _t.start(); }
};
class TraceCPUTime: public StackObj {
private:
bool _active; // true if times will be measured and printed

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/timerTrace.hpp"
TraceTime::TraceTime(const char* title,
bool doit) {
_active = doit;
_verbose = true;
_title = title;
_print = NULL;
if (_active) {
_accum = NULL;
_t.start();
}
}
TraceTime::TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit,
bool verbose) {
_active = doit;
_verbose = verbose;
_title = title;
_print = NULL;
if (_active) {
_accum = accumulator;
_t.start();
}
}
TraceTime::TraceTime(const char* title,
TraceTimerLogPrintFunc ttlpf) {
_active = ttlpf!= NULL;
_verbose = true;
_title = title;
_print = ttlpf;
if (_active) {
_accum = NULL;
_t.start();
}
}
TraceTime::~TraceTime() {
if (!_active) {
return;
}
_t.stop();
if (_accum != NULL) {
_accum->add(_t);
}
if (!_verbose) {
return;
}
if (_print) {
_print("%s, %3.7f secs", _title, _t.seconds());
} else {
tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds());
tty->flush();
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_RUNTIME_TIMERTRACE_HPP
#define SHARE_VM_RUNTIME_TIMERTRACE_HPP
#include "logging/log.hpp"
#include "utilities/globalDefinitions.hpp"
// TraceTime is used for tracing the execution time of a block
// Usage:
// {
// TraceTime t("some timer", TIMERTRACE_LOG(Info, startuptime, tagX...));
// some_code();
// }
//
typedef void (*TraceTimerLogPrintFunc)(const char*, ...);
// We need to explicit take address of Log<>write<> and static cast
// due to MSVC is not compliant with templates two-phase lookup
#define TRACETIME_LOG(TT_LEVEL, ...) \
log_is_enabled(TT_LEVEL, __VA_ARGS__) ? static_cast<TraceTimerLogPrintFunc>(&Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::TT_LEVEL>) : (TraceTimerLogPrintFunc)NULL
class TraceTime: public StackObj {
private:
bool _active; // do timing
bool _verbose; // report every timing
elapsedTimer _t; // timer
elapsedTimer* _accum; // accumulator
const char* _title; // name of timer
TraceTimerLogPrintFunc _print;
public:
// Constructors
TraceTime(const char* title,
bool doit = true);
TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit = true,
bool verbose = false);
TraceTime(const char* title,
TraceTimerLogPrintFunc ttlpf);
~TraceTime();
// Accessors
void set_verbose(bool verbose) { _verbose = verbose; }
bool verbose() const { return _verbose; }
// Activation
void suspend() { if (_active) _t.stop(); }
void resume() { if (_active) _t.start(); }
};
#endif // SHARE_VM_RUNTIME_TIMERTRACE_HPP