Commit 13ebc734 authored by ssid's avatar ssid Committed by Commit bot

[tracing] Introduce BACKGROUND mode in MemoryInfra

This CL makes following changes:
1. Adds a BACKGROUND mode in the dump triggers in trace config.
1. Periodic dumps can be disabled on passing 0 as interval.
2. On BACKGROUND mode only whitelisted dump providers are invoked.
3. Clean up periodic dump timer set up.
4. MemoryDumpSessionState is initialized with config in the renderer
   also.

BUG=613198

Review-Url: https://codereview.chromium.org/1995573003
Cr-Commit-Position: refs/heads/master@{#396927}
parent 60506c59
This diff is collapsed.
......@@ -141,6 +141,11 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
dumper_registrations_ignored_for_testing_ = ignored;
}
// Resets the dump provider whitelist to the list given.
void set_dump_provider_whitelist_for_testing(const char* const* list) {
dump_provider_whitelist_ = list;
}
private:
friend std::default_delete<MemoryDumpManager>; // For the testing instance.
friend struct DefaultSingletonTraits<MemoryDumpManager>;
......@@ -176,7 +181,8 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
MemoryDumpProviderInfo(MemoryDumpProvider* dump_provider,
const char* name,
scoped_refptr<SequencedTaskRunner> task_runner,
const MemoryDumpProvider::Options& options);
const MemoryDumpProvider::Options& options,
bool whitelisted_for_background_mode);
MemoryDumpProvider* const dump_provider;
......@@ -200,6 +206,9 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
// Flagged either by the auto-disable logic or during unregistration.
bool disabled;
// True if the dump provider is whitelisted for background mode.
const bool whitelisted_for_background_mode;
private:
friend class base::RefCountedThreadSafe<MemoryDumpProviderInfo>;
~MemoryDumpProviderInfo();
......@@ -262,6 +271,31 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState);
};
// Sets up periodic memory dump timers to start global dump requests based on
// the dump triggers from trace config.
class BASE_EXPORT PeriodicGlobalDumpTimer {
public:
PeriodicGlobalDumpTimer();
~PeriodicGlobalDumpTimer();
void Start(const std::vector<TraceConfig::MemoryDumpConfig::Trigger>&
triggers_list);
void Stop();
bool IsRunning();
private:
// Periodically called by the timer.
void RequestPeriodicGlobalDump();
RepeatingTimer timer_;
uint32_t periodic_dumps_count_;
uint32_t light_dump_rate_;
uint32_t heavy_dump_rate_;
DISALLOW_COPY_AND_ASSIGN(PeriodicGlobalDumpTimer);
};
static const int kMaxConsecutiveFailuresCount;
static const char* const kSystemAllocatorPoolName;
......@@ -325,12 +359,15 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
subtle::AtomicWord memory_tracing_enabled_;
// For time-triggered periodic dumps.
RepeatingTimer periodic_dump_timer_;
PeriodicGlobalDumpTimer periodic_dump_timer_;
// Thread used for MemoryDumpProviders which don't specify a task runner
// affinity.
std::unique_ptr<Thread> dump_thread_;
// List of names of the dump providers whitelisted for background mode.
const char* const* dump_provider_whitelist_;
// The unique id of the child process. This is created only for tracing and is
// expected to be valid only when tracing is enabled.
uint64_t tracing_process_id_;
......
......@@ -48,16 +48,24 @@ MATCHER(IsLightDump, "") {
return arg.level_of_detail == MemoryDumpLevelOfDetail::LIGHT;
}
MATCHER(IsBackgroundDump, "") {
return arg.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND;
}
namespace {
const char* kMDPName = "TestDumpProvider";
const char* kWhitelistedMDPName = "WhitelistedTestDumpProvider";
const char* const kTestMDPWhitelist[] = {kWhitelistedMDPName, nullptr};
void RegisterDumpProvider(
MemoryDumpProvider* mdp,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const MemoryDumpProvider::Options& options) {
const MemoryDumpProvider::Options& options,
const char* name = kMDPName) {
MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
mdm->set_dumper_registrations_ignored_for_testing(false);
const char* kMDPName = "TestDumpProvider";
mdm->RegisterDumpProvider(mdp, kMDPName, std::move(task_runner), options);
mdm->RegisterDumpProvider(mdp, name, std::move(task_runner), options);
mdm->set_dumper_registrations_ignored_for_testing(true);
}
......@@ -71,7 +79,6 @@ void RegisterDumpProviderWithSequencedTaskRunner(
const MemoryDumpProvider::Options& options) {
MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
mdm->set_dumper_registrations_ignored_for_testing(false);
const char* kMDPName = "TestDumpProvider";
mdm->RegisterDumpProviderWithSequencedTaskRunner(mdp, kMDPName, task_runner,
options);
mdm->set_dumper_registrations_ignored_for_testing(true);
......@@ -1099,5 +1106,48 @@ TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoonDuringDump) {
DisableTracing();
}
TEST_F(MemoryDumpManagerTest, TestWhitelistingMDP) {
InitializeMemoryDumpManager(false /* is_coordinator */);
mdm_->set_dump_provider_whitelist_for_testing(kTestMDPWhitelist);
std::unique_ptr<MockMemoryDumpProvider> mdp1(new MockMemoryDumpProvider);
RegisterDumpProvider(mdp1.get());
std::unique_ptr<MockMemoryDumpProvider> mdp2(new MockMemoryDumpProvider);
RegisterDumpProvider(mdp2.get(), nullptr, kDefaultOptions,
kWhitelistedMDPName);
EXPECT_CALL(*mdp1, OnMemoryDump(_, _)).Times(0);
EXPECT_CALL(*mdp2, OnMemoryDump(_, _)).Times(1).WillOnce(Return(true));
EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
EXPECT_FALSE(IsPeriodicDumpingEnabled());
RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
MemoryDumpLevelOfDetail::BACKGROUND);
DisableTracing();
}
TEST_F(MemoryDumpManagerTest, TestBackgroundTracingSetup) {
InitializeMemoryDumpManager(true /* is_coordinator */);
RunLoop run_loop;
auto quit_closure = run_loop.QuitClosure();
testing::InSequence sequence;
EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
.Times(5);
EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
.WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args,
const MemoryDumpCallback& callback) {
ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure);
}));
EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(AnyNumber());
EnableTracingWithTraceConfig(
TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger());
ASSERT_TRUE(IsPeriodicDumpingEnabled());
run_loop.Run();
DisableTracing();
}
} // namespace trace_event
} // namespace base
......@@ -28,6 +28,8 @@ const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
const char* MemoryDumpLevelOfDetailToString(
const MemoryDumpLevelOfDetail& level_of_detail) {
switch (level_of_detail) {
case MemoryDumpLevelOfDetail::BACKGROUND:
return "background";
case MemoryDumpLevelOfDetail::LIGHT:
return "light";
case MemoryDumpLevelOfDetail::DETAILED:
......@@ -39,6 +41,8 @@ const char* MemoryDumpLevelOfDetailToString(
MemoryDumpLevelOfDetail StringToMemoryDumpLevelOfDetail(
const std::string& str) {
if (str == "background")
return MemoryDumpLevelOfDetail::BACKGROUND;
if (str == "light")
return MemoryDumpLevelOfDetail::LIGHT;
if (str == "detailed")
......
......@@ -28,13 +28,24 @@ enum class MemoryDumpType {
};
// Tells the MemoryDumpProvider(s) how much detailed their dumps should be.
// MemoryDumpProvider instances must guarantee that level of detail does not
// affect the total size reported in the root node, but only the granularity of
// the child MemoryAllocatorDump(s).
enum class MemoryDumpLevelOfDetail {
LIGHT, // Few entries, typically a fixed number, per dump.
DETAILED, // Unrestricted amount of entries per dump.
LAST = DETAILED // For IPC Macros.
// For background tracing mode. The dump time is quick, and typically just the
// totals are expected. Suballocations need not be specified. Dump name must
// contain only pre-defined strings and string arguments cannot be added.
BACKGROUND,
// For the levels below, MemoryDumpProvider instances must guarantee that the
// total size reported in the root node is consistent. Only the granularity of
// the child MemoryAllocatorDump(s) differs with the levels.
// Few entries, typically a fixed number, per dump.
LIGHT,
// Unrestricted amount of entries per dump.
DETAILED,
// For IPC Macros.
LAST = DETAILED
};
// Initial request arguments for a global memory dump. (see
......
......@@ -71,6 +71,27 @@ class TraceConfigMemoryTestUtil {
"\"record_mode\":\"record-until-full\""
"}", MemoryDumpManager::kTraceCategory);
}
static std::string GetTraceConfig_BackgroundTrigger() {
return StringPrintf(
"{"
"\"enable_argument_filter\":false,"
"\"enable_sampling\":false,"
"\"enable_systrace\":false,"
"\"included_categories\":["
"\"%s\""
"],"
"\"memory_dump_config\":{"
"\"triggers\":["
"{"
"\"mode\":\"background\","
"\"periodic_interval_ms\":1"
"}"
"]"
"},"
"\"record_mode\":\"record-until-full\""
"}", MemoryDumpManager::kTraceCategory);
}
};
} // namespace trace_event
......
......@@ -568,22 +568,33 @@ TEST(TraceConfigTest, SetTraceOptionValues) {
}
TEST(TraceConfigTest, TraceConfigFromMemoryConfigString) {
std::string tc_str =
std::string tc_str1 =
TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(200, 2000);
TraceConfig tc(tc_str);
EXPECT_EQ(tc_str, tc.ToString());
EXPECT_TRUE(tc.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
ASSERT_EQ(2u, tc.memory_dump_config_.triggers.size());
TraceConfig tc1(tc_str1);
EXPECT_EQ(tc_str1, tc1.ToString());
EXPECT_TRUE(tc1.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
ASSERT_EQ(2u, tc1.memory_dump_config_.triggers.size());
EXPECT_EQ(200u, tc.memory_dump_config_.triggers[0].periodic_interval_ms);
EXPECT_EQ(200u, tc1.memory_dump_config_.triggers[0].periodic_interval_ms);
EXPECT_EQ(MemoryDumpLevelOfDetail::LIGHT,
tc.memory_dump_config_.triggers[0].level_of_detail);
tc1.memory_dump_config_.triggers[0].level_of_detail);
EXPECT_EQ(2000u, tc.memory_dump_config_.triggers[1].periodic_interval_ms);
EXPECT_EQ(2000u, tc1.memory_dump_config_.triggers[1].periodic_interval_ms);
EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
tc.memory_dump_config_.triggers[1].level_of_detail);
EXPECT_EQ(2048u, tc.memory_dump_config_.heap_profiler_options.
breakdown_threshold_bytes);
tc1.memory_dump_config_.triggers[1].level_of_detail);
EXPECT_EQ(
2048u,
tc1.memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes);
std::string tc_str2 =
TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger();
TraceConfig tc2(tc_str2);
EXPECT_EQ(tc_str2, tc2.ToString());
EXPECT_TRUE(tc2.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
ASSERT_EQ(1u, tc2.memory_dump_config_.triggers.size());
EXPECT_EQ(1u, tc2.memory_dump_config_.triggers[0].periodic_interval_ms);
EXPECT_EQ(MemoryDumpLevelOfDetail::BACKGROUND,
tc2.memory_dump_config_.triggers[0].level_of_detail);
}
TEST(TraceConfigTest, EmptyMemoryDumpConfigTest) {
......
......@@ -131,7 +131,8 @@ class ChildTracingTest : public content::RenderViewTest, public IPC::Listener {
// checks that the child actually sends a response to that.
void RequestProcessMemoryDumpAndCheckResponse(uint64_t dump_guid) {
SimulateSyntheticMessageFromBrowser(TracingMsg_ProcessMemoryDumpRequest(
{dump_guid, MemoryDumpType::EXPLICITLY_TRIGGERED}));
{dump_guid, MemoryDumpType::EXPLICITLY_TRIGGERED,
MemoryDumpLevelOfDetail::DETAILED}));
// Check that a child -> browser response to the local dump request is sent.
const IPC::Message* msg =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment