Skip to content

Commit

Permalink
memory-infra: get rid of MemoryDumpManager::RequestGlobalDump method.
Browse files Browse the repository at this point in the history
This CL gets rid of the MemoryDumpManager::RequestGlobalDump(),
and moves the existing code to use the service. This allows to
cleanup all the odd callback proxy required to match the base vs
mojo callbacks.
Also, this moves the dump id generation responsibility to the
service, which is now the only one dealing with global dumps.

At this point the only knowledge left in base::MemoryDumpManager
about "global" dumps is only the |request_dump_function|, which
is required to keep the periodic dump scheduler and peak detector
working. This can be removed once those two are moved to the service.

BUG=720352

Change-Id: I25c22157234e1e627c5aeafa189df01944354e7d
Reviewed-on: https://chromium-review.googlesource.com/536952
Commit-Queue: Primiano Tucci <primiano@chromium.org>
Reviewed-by: siddhartha sivakumar <ssid@chromium.org>
Reviewed-by: Hector Dearman <hjd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#481678}
  • Loading branch information
primiano authored and Commit Bot committed Jun 22, 2017
1 parent fed6d12 commit 5640bf1
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 218 deletions.
90 changes: 22 additions & 68 deletions base/trace_event/memory_dump_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,8 @@ namespace trace_event {

namespace {

StaticAtomicSequenceNumber g_next_guid;
MemoryDumpManager* g_instance_for_testing = nullptr;

// Callback wrapper to hook upon the completion of RequestGlobalDump() and
// inject trace markers.
void OnGlobalDumpDone(GlobalMemoryDumpCallback wrapped_callback,
uint64_t dump_guid,
bool success) {
char guid_str[20];
sprintf(guid_str, "0x%" PRIx64, dump_guid);
TRACE_EVENT_NESTABLE_ASYNC_END2(MemoryDumpManager::kTraceCategory,
"GlobalMemoryDump", TRACE_ID_LOCAL(dump_guid),
"dump_guid", TRACE_STR_COPY(guid_str),
"success", success);

if (!wrapped_callback.is_null()) {
wrapped_callback.Run(dump_guid, success);
wrapped_callback.Reset();
}
}

void FillOsDumpFromProcessMemoryDump(
const ProcessMemoryDump* pmd,
MemoryDumpCallbackResult::OSMemDump* osDump) {
Expand All @@ -81,14 +62,18 @@ void FillOsDumpFromProcessMemoryDump(
}
}

void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) {
MemoryDumpManager::GetInstance()->RequestGlobalDump(
MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail);
}

void OnPeriodicSchedulerTick(MemoryDumpLevelOfDetail level_of_detail) {
MemoryDumpManager::GetInstance()->RequestGlobalDump(
MemoryDumpType::PERIODIC_INTERVAL, level_of_detail);
// Temporary (until peak detector and scheduler are moved outside of here)
// trampoline function to match the |request_dump_function| passed to Initialize
// to the callback expected by MemoryPeakDetector and MemoryDumpScheduler.
// TODO(primiano): remove this.
void DoGlobalDumpWithoutCallback(
MemoryDumpManager::RequestGlobalDumpFunction global_dump_fn,
MemoryDumpType dump_type,
MemoryDumpLevelOfDetail level_of_detail) {
// The actual dump_guid will be set by service. TODO(primiano): remove
// guid from the request args API.
MemoryDumpRequestArgs args{0 /* dump_guid */, dump_type, level_of_detail};
global_dump_fn.Run(args);
}

} // namespace
Expand Down Expand Up @@ -134,8 +119,6 @@ MemoryDumpManager::MemoryDumpManager()
tracing_process_id_(kInvalidTracingProcessId),
dumper_registrations_ignored_for_testing_(false),
heap_profiling_enabled_(false) {
g_next_guid.GetNext(); // Make sure that first guid is not zero.

// At this point the command line may not be initialized but we try to
// enable the heap profiler to capture allocations as soon as possible.
EnableHeapProfilingIfNeeded();
Expand Down Expand Up @@ -402,35 +385,6 @@ void MemoryDumpManager::UnregisterDumpProviderInternal(
dump_providers_.erase(mdp_iter);
}

void MemoryDumpManager::RequestGlobalDump(
MemoryDumpType dump_type,
MemoryDumpLevelOfDetail level_of_detail,
const GlobalMemoryDumpCallback& callback) {
if (!is_initialized()) {
VLOG(1) << "RequestGlobalDump() FAIL: MemoryDumpManager is not initialized";
if (!callback.is_null())
callback.Run(0u /* guid */, false /* success */);
return;
}

const uint64_t guid =
TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());

// Creates an async event to keep track of the global dump evolution.
// The |wrapped_callback| will generate the ASYNC_END event and then invoke
// the real |callback| provided by the caller.
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type",
MemoryDumpTypeToString(dump_type), "level_of_detail",
MemoryDumpLevelOfDetailToString(level_of_detail));
GlobalMemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback);

// The embedder will coordinate the IPC broadcast and at some point invoke
// CreateProcessDump() to get a dump for the current process.
MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail};
request_dump_function_.Run(args, wrapped_callback);
}

void MemoryDumpManager::GetDumpProvidersForPolling(
std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) {
DCHECK(providers->empty());
Expand All @@ -441,13 +395,6 @@ void MemoryDumpManager::GetDumpProvidersForPolling(
}
}

void MemoryDumpManager::RequestGlobalDump(
MemoryDumpType dump_type,
MemoryDumpLevelOfDetail level_of_detail) {
auto noop_callback = [](uint64_t dump_guid, bool success) {};
RequestGlobalDump(dump_type, level_of_detail, Bind(noop_callback));
}

bool MemoryDumpManager::IsDumpProviderRegisteredForTesting(
MemoryDumpProvider* provider) {
AutoLock lock(lock_);
Expand Down Expand Up @@ -811,7 +758,9 @@ void MemoryDumpManager::SetupForTracing(
for (const auto& trigger : memory_dump_config.triggers) {
if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
if (periodic_config.triggers.empty()) {
periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick);
periodic_config.callback =
BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
MemoryDumpType::PERIODIC_INTERVAL);
}
periodic_config.triggers.push_back(
{trigger.level_of_detail, trigger.min_time_between_dumps_ms});
Expand All @@ -823,7 +772,9 @@ void MemoryDumpManager::SetupForTracing(
BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling,
Unretained(this)),
GetOrCreateBgTaskRunnerLocked(),
BindRepeating(&OnPeakDetected, trigger.level_of_detail));
BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
MemoryDumpType::PEAK_MEMORY_USAGE,
trigger.level_of_detail));

MemoryPeakDetector::Config peak_config;
peak_config.polling_interval_ms = 10;
Expand All @@ -836,7 +787,10 @@ void MemoryDumpManager::SetupForTracing(
// gives a good reference point for analyzing the trace.
if (is_coordinator_) {
GetOrCreateBgTaskRunnerLocked()->PostTask(
FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail));
FROM_HERE,
BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
MemoryDumpType::PEAK_MEMORY_USAGE,
trigger.level_of_detail));
}
}
}
Expand Down
44 changes: 15 additions & 29 deletions base/trace_event/memory_dump_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ enum HeapProfilingMode {
class BASE_EXPORT MemoryDumpManager {
public:
using RequestGlobalDumpFunction =
RepeatingCallback<void(const MemoryDumpRequestArgs& args,
const GlobalMemoryDumpCallback& callback)>;
RepeatingCallback<void(const MemoryDumpRequestArgs& args)>;

static const char* const kTraceCategory;

Expand All @@ -66,12 +65,15 @@ class BASE_EXPORT MemoryDumpManager {
// Initialization can happen after (Un)RegisterMemoryDumpProvider() calls
// and the MemoryDumpManager guarantees to support this.
// On the other side, the MemoryDumpManager will not be fully operational
// (i.e. will NACK any RequestGlobalMemoryDump()) until initialized.
// (any CreateProcessDump() will return a failure) until initialized.
// Arguments:
// request_dump_function: Function to invoke a global dump. Global dump
// involves embedder-specific behaviors like multiprocess handshaking.
// is_coordinator: True when current process coordinates the periodic dump
// triggering.
// request_dump_function: Function to invoke a global dump. Global dump
// involves embedder-specific behaviors like multiprocess handshaking.
// TODO(primiano): this is only required to trigger global dumps from
// the scheduler and the peak detector. Should be removed once they are
// both moved out of base.
void Initialize(RequestGlobalDumpFunction request_dump_function,
bool is_coordinator);

Expand Down Expand Up @@ -112,36 +114,20 @@ class BASE_EXPORT MemoryDumpManager {
void UnregisterAndDeleteDumpProviderSoon(
std::unique_ptr<MemoryDumpProvider> mdp);

// Requests a memory dump. The dump might happen or not depending on the
// filters and categories specified when enabling tracing.
// A SUMMARY_ONLY dump can be requested at any time after initialization and
// other type of dumps can be requested only when MDM is enabled.
// The optional |callback| is executed asynchronously, on an arbitrary thread,
// to notify about the completion of the global dump (i.e. after all the
// processes have dumped) and its success (true iff all the dumps were
// successful).
void RequestGlobalDump(MemoryDumpType,
MemoryDumpLevelOfDetail,
const GlobalMemoryDumpCallback&);

// Same as above (still asynchronous), but without callback.
void RequestGlobalDump(MemoryDumpType, MemoryDumpLevelOfDetail);

// Prepare MemoryDumpManager for RequestGlobalMemoryDump calls for tracing
// related modes (non-SUMMARY_ONLY).
// Initializes the peak detector, scheduler and heap profiler with the given
// config.
// Prepare MemoryDumpManager for CreateProcessDump() calls for tracing-related
// modes (i.e. |level_of_detail| != SUMMARY_ONLY).
// Also initializes the peak detector, scheduler and heap profiler with the
// given config.
void SetupForTracing(const TraceConfig::MemoryDumpConfig&);

// Tear-down tracing related state.
// Non-tracing modes (e.g. SUMMARY_ONLY) will continue to work.
void TeardownForTracing();

// NOTE: Use RequestGlobalDump() to create memory dumps. Creates a memory dump
// for the current process and appends it to the trace. |callback| will be
// invoked asynchronously upon completion on the same thread on which
// CreateProcessDump() was called. This method should only be used by the
// embedder while creating a global memory dump.
// Creates a memory dump for the current process and appends it to the trace.
// |callback| will be invoked asynchronously upon completion on the same
// thread on which CreateProcessDump() was called. This method should only be
// used by the memory-infra service while creating a global memory dump.
void CreateProcessDump(const MemoryDumpRequestArgs& args,
const ProcessMemoryDumpCallback& callback);

Expand Down
15 changes: 2 additions & 13 deletions base/trace_event/memory_dump_manager_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,9 @@
namespace base {
namespace trace_event {

// Short-circuit the RequestGlobalDump() calls to CreateProcessDump().
// Rationale: only the in-process logic is required for unittests.
void RequestGlobalDumpForInProcessTesting(
const MemoryDumpRequestArgs& args,
const GlobalMemoryDumpCallback& global_callback) {
// Turns a ProcessMemoryDumpCallback into a GlobalMemoryDumpCallback.
auto callback_adapter = [](const GlobalMemoryDumpCallback& global_callback,
uint64_t dump_guid, bool success,
const Optional<MemoryDumpCallbackResult>& result) {
if (!global_callback.is_null())
global_callback.Run(dump_guid, success);
};
void RequestGlobalDumpForInProcessTesting(const MemoryDumpRequestArgs& args) {
MemoryDumpManager::GetInstance()->CreateProcessDump(
args, Bind(callback_adapter, global_callback));
args, ProcessMemoryDumpCallback());
};

// Short circuits the RequestGlobalDumpFunction() to CreateProcessDump(),
Expand Down
2 changes: 1 addition & 1 deletion base/trace_event/memory_dump_request_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct BASE_EXPORT MemoryDumpCallbackResult {
};

using GlobalMemoryDumpCallback =
Callback<void(uint64_t dump_guid, bool success)>;
Callback<void(bool success, uint64_t dump_guid)>;

using ProcessMemoryDumpCallback =
Callback<void(uint64_t dump_guid,
Expand Down
24 changes: 11 additions & 13 deletions content/browser/tracing/memory_tracing_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "testing/gmock/include/gmock/gmock.h"

using base::trace_event::MemoryDumpArgs;
Expand All @@ -43,28 +44,20 @@ class MockDumpProvider : public base::trace_event::MemoryDumpProvider {

class MemoryTracingTest : public ContentBrowserTest {
public:
void DoRequestGlobalDump(
const MemoryDumpType& dump_type,
const MemoryDumpLevelOfDetail& level_of_detail,
const base::trace_event::GlobalMemoryDumpCallback& cb) {
MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type,
level_of_detail, cb);
}

// Used as callback argument for MemoryDumpManager::RequestGlobalDump():
void OnGlobalMemoryDumpDone(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::Closure closure,
uint32_t request_index,
uint64_t dump_guid,
bool success) {
bool success,
uint64_t dump_guid) {
// Make sure we run the RunLoop closure on the same thread that originated
// the run loop (which is the IN_PROC_BROWSER_TEST_F main thread).
if (!task_runner->RunsTasksInCurrentSequence()) {
task_runner->PostTask(
FROM_HERE, base::Bind(&MemoryTracingTest::OnGlobalMemoryDumpDone,
base::Unretained(this), task_runner, closure,
request_index, dump_guid, success));
request_index, success, dump_guid));
return;
}
if (success)
Expand All @@ -85,10 +78,15 @@ class MemoryTracingTest : public ContentBrowserTest {
base::ThreadTaskRunnerHandle::Get(), closure, request_index);
if (from_renderer_thread) {
PostTaskToInProcessRendererAndWait(base::Bind(
&MemoryTracingTest::DoRequestGlobalDump, base::Unretained(this),
&memory_instrumentation::MemoryInstrumentation::
RequestGlobalDumpAndAppendToTrace,
base::Unretained(
memory_instrumentation::MemoryInstrumentation::GetInstance()),
dump_type, level_of_detail, callback));
} else {
DoRequestGlobalDump(dump_type, level_of_detail, callback);
memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestGlobalDumpAndAppendToTrace(dump_type, level_of_detail,
callback);
}
}

Expand Down
Loading

0 comments on commit 5640bf1

Please sign in to comment.