Skip to content

Commit

Permalink
8237354: Add option to jcmd to write a gzipped heap dump
Browse files Browse the repository at this point in the history
Reviewed-by: rschmelter, clanger
Backport-of: 19be497
  • Loading branch information
Bin Liao authored and RealCLanger committed Sep 13, 2021
1 parent 126f1a2 commit 1868c15
Show file tree
Hide file tree
Showing 13 changed files with 1,706 additions and 121 deletions.
23 changes: 19 additions & 4 deletions src/hotspot/share/gc/shared/workgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ void AbstractWorkGang::threads_do(ThreadClosure* tc) const {
}
}

static void run_foreground_task_if_needed(AbstractGangTask* task, uint num_workers,
bool add_foreground_work) {
if (add_foreground_work) {
log_develop_trace(gc, workgang)("Running work gang: %s task: %s worker: foreground",
Thread::current()->name(), task->name());
task->work(num_workers);
log_develop_trace(gc, workgang)("Finished work gang: %s task: %s worker: foreground "
"thread: " PTR_FORMAT, Thread::current()->name(), task->name(), p2i(Thread::current()));
}
}

// WorkGang dispatcher implemented with semaphores.
//
// Semaphores don't require the worker threads to re-claim the lock when they wake up.
Expand Down Expand Up @@ -136,14 +147,16 @@ class SemaphoreGangTaskDispatcher : public GangTaskDispatcher {
delete _end_semaphore;
}

void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) {
void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers, bool add_foreground_work) {
// No workers are allowed to read the state variables until they have been signaled.
_task = task;
_not_finished = num_workers;

// Dispatch 'num_workers' number of tasks.
_start_semaphore->signal(num_workers);

run_foreground_task_if_needed(task, num_workers, add_foreground_work);

// Wait for the last worker to signal the coordinator.
_end_semaphore->wait();

Expand Down Expand Up @@ -199,7 +212,7 @@ class MutexGangTaskDispatcher : public GangTaskDispatcher {
delete _monitor;
}

void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) {
void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers, bool add_foreground_work) {
MutexLockerEx ml(_monitor, Mutex::_no_safepoint_check_flag);

_task = task;
Expand All @@ -208,6 +221,8 @@ class MutexGangTaskDispatcher : public GangTaskDispatcher {
// Tell the workers to get to work.
_monitor->notify_all();

run_foreground_task_if_needed(task, num_workers, add_foreground_work);

// Wait for them to finish.
while (_finished < _num_workers) {
_monitor->wait(/* no_safepoint_check */ true);
Expand Down Expand Up @@ -274,14 +289,14 @@ void WorkGang::run_task(AbstractGangTask* task) {
run_task(task, active_workers());
}

void WorkGang::run_task(AbstractGangTask* task, uint num_workers) {
void WorkGang::run_task(AbstractGangTask* task, uint num_workers, bool add_foreground_work) {
guarantee(num_workers <= total_workers(),
"Trying to execute task %s with %u workers which is more than the amount of total workers %u.",
task->name(), num_workers, total_workers());
guarantee(num_workers > 0, "Trying to execute task %s with zero workers", task->name());
uint old_num_workers = _active_workers;
update_active_workers(num_workers);
_dispatcher->coordinator_execute_on_workers(task, num_workers);
_dispatcher->coordinator_execute_on_workers(task, num_workers, add_foreground_work);
update_active_workers(old_num_workers);
}

Expand Down
8 changes: 5 additions & 3 deletions src/hotspot/share/gc/shared/workgroup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ class GangTaskDispatcher : public CHeapObj<mtGC> {

// Distributes the task out to num_workers workers.
// Returns when the task has been completed by all workers.
virtual void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) = 0;
virtual void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers,
bool add_foreground_work) = 0;

// Worker API.

Expand Down Expand Up @@ -243,8 +244,9 @@ class WorkGang: public AbstractWorkGang {
// Run a task with the given number of workers, returns
// when the task is done. The number of workers must be at most the number of
// active workers. Additional workers may be created if an insufficient
// number currently exists.
void run_task(AbstractGangTask* task, uint num_workers);
// number currently exists. If the add_foreground_work flag is true, the current thread
// is used to run the task too.
void run_task(AbstractGangTask* task, uint num_workers, bool add_foreground_work = false);

protected:
virtual AbstractGangWorker* allocate_worker(uint which);
Expand Down
17 changes: 16 additions & 1 deletion src/hotspot/share/services/diagnosticCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,19 +507,34 @@ HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
_filename("filename","Name of the dump file", "STRING",true),
_all("-all", "Dump all objects, including unreachable objects",
"BOOLEAN", false, "false"),
_gzip("-gz", "If specified, the heap dump is written in gzipped format "
"using the given compression level. 1 (recommended) is the fastest, "
"9 the strongest compression.", "INT", false, "1"),
_overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",
"BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_argument(&_filename);
_dcmdparser.add_dcmd_option(&_gzip);
_dcmdparser.add_dcmd_option(&_overwrite);
}

void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
jlong level = -1; // -1 means no compression.

if (_gzip.is_set()) {
level = _gzip.value();

if (level < 1 || level > 9) {
output()->print_cr("Compression level out of range (1-9): " JLONG_FORMAT, level);
return;
}
}

// Request a full GC before heap dump if _all is false
// This helps reduces the amount of unreachable objects in the dump
// and makes it easier to browse.
HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
dumper.dump(_filename.value(), output(), _overwrite.value());
dumper.dump(_filename.value(), output(), (int) level, _overwrite.value());
}

int HeapDumpDCmd::num_arguments() {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/services/diagnosticCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ class HeapDumpDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _filename;
DCmdArgument<bool> _all;
DCmdArgument<jlong> _gzip;
DCmdArgument<bool> _overwrite;
public:
HeapDumpDCmd(outputStream* output, bool heap);
Expand Down
Loading

1 comment on commit 1868c15

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.