Detect child tasks born during a profiled tasks
r=rtenneti
Review URL: http://codereview.chromium.org/8894022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114336 0039d316-1c4b-4281-b951-d872f2087c98
CrOS-Libchrome-Original-Commit: 8aa1e6e66cc7c3eab00f3438262c4a309c9f9b92
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc
index 8282444..53faa6a 100644
--- a/base/tracked_objects_unittest.cc
+++ b/base/tracked_objects_unittest.cc
@@ -46,9 +46,11 @@
EXPECT_EQ(data, ThreadData::Get());
ThreadData::BirthMap birth_map;
ThreadData::DeathMap death_map;
- data->SnapshotMaps(false, &birth_map, &death_map);
+ ThreadData::ParentChildSet parent_child_set;
+ data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
EXPECT_EQ(0u, birth_map.size());
EXPECT_EQ(0u, death_map.size());
+ EXPECT_EQ(0u, parent_child_set.size());
// Cleanup with no leaking.
ShutdownSingleThreadedCleanup(false);
@@ -62,9 +64,10 @@
EXPECT_EQ(data, ThreadData::Get());
birth_map.clear();
death_map.clear();
- data->SnapshotMaps(false, &birth_map, &death_map);
+ data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
EXPECT_EQ(0u, birth_map.size());
EXPECT_EQ(0u, death_map.size());
+ EXPECT_EQ(0u, parent_child_set.size());
}
TEST_F(TrackedObjectsTest, TinyStartupShutdown) {
@@ -73,7 +76,7 @@
// Instigate tracking on a single tracked object, on our thread.
const Location& location = FROM_HERE;
- ThreadData::TallyABirthIfActive(location);
+ Births* first_birth = ThreadData::TallyABirthIfActive(location);
ThreadData* data = ThreadData::first();
ASSERT_TRUE(data);
@@ -81,33 +84,134 @@
EXPECT_EQ(data, ThreadData::Get());
ThreadData::BirthMap birth_map;
ThreadData::DeathMap death_map;
- data->SnapshotMaps(false, &birth_map, &death_map);
+ ThreadData::ParentChildSet parent_child_set;
+ data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
EXPECT_EQ(1u, birth_map.size()); // 1 birth location.
EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth.
EXPECT_EQ(0u, death_map.size()); // No deaths.
+ EXPECT_EQ(0u, parent_child_set.size()); // No children.
- // Now instigate another birth, and a first death at the same location.
+ // Now instigate another birth, while we are timing the run of the first
+ // execution.
+ TrackedTime start_time =
+ ThreadData::NowForStartOfRun(first_birth);
+ // Create a child (using the same birth location).
// TrackingInfo will call TallyABirth() during construction.
- base::TimeTicks kBogusStartTime;
- base::TrackingInfo pending_task(location, kBogusStartTime);
- TrackedTime kBogusStartRunTime;
- TrackedTime kBogusEndRunTime;
- ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, kBogusStartRunTime,
- kBogusEndRunTime);
+ base::TimeTicks kBogusBirthTime;
+ base::TrackingInfo pending_task(location, kBogusBirthTime);
+ // Finally conclude the outer run.
+ TrackedTime end_time = ThreadData::NowForEndOfRun();
+ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, start_time,
+ end_time);
birth_map.clear();
death_map.clear();
- data->SnapshotMaps(false, &birth_map, &death_map);
+ parent_child_set.clear();
+ data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
EXPECT_EQ(1u, birth_map.size()); // 1 birth location.
EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births.
EXPECT_EQ(1u, death_map.size()); // 1 location.
EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death.
+ if (ThreadData::tracking_parent_child_status()) {
+ EXPECT_EQ(1u, parent_child_set.size()); // 1 child.
+ EXPECT_EQ(parent_child_set.begin()->first,
+ parent_child_set.begin()->second);
+ } else {
+ EXPECT_EQ(0u, parent_child_set.size()); // no stats.
+ }
// The births were at the same location as the one known death.
EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first);
}
+TEST_F(TrackedObjectsTest, ParentChildTest) {
+ if (!ThreadData::InitializeAndSetTrackingStatus(true))
+ return;
+ if (!ThreadData::tracking_parent_child_status())
+ return; // Feature not compiled in.
+
+ // Instigate tracking on a single tracked object, on our thread.
+ const int kFakeLineNumber = 1776;
+ const char* kFile = "FixedUnitTestFileName";
+ const char* kFunction = "ParentChildTest";
+ Location location(kFunction, kFile, kFakeLineNumber, NULL);
+ Births* first_birth = ThreadData::TallyABirthIfActive(location);
+
+ // Now instigate another birth, while we are timing the run of the first
+ // execution.
+ TrackedTime start_time =
+ ThreadData::NowForStartOfRun(first_birth);
+ // Create a child (using the same birth location).
+ // TrackingInfo will call TallyABirth() during construction.
+ base::TimeTicks kBogusBirthTime;
+ base::TrackingInfo pending_task(location, kBogusBirthTime);
+
+ // Don't conclude the run, so that we don't use the actual timer that we
+ // started for the outer profile. This way the JSON will not include some
+ // random time.
+ ThreadData* data = ThreadData::first();
+ ASSERT_TRUE(data);
+ EXPECT_TRUE(!data->next());
+ EXPECT_EQ(data, ThreadData::Get());
+
+ ThreadData::BirthMap birth_map;
+ ThreadData::DeathMap death_map;
+ ThreadData::ParentChildSet parent_child_set;
+
+ data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
+ EXPECT_EQ(1u, birth_map.size()); // 1 birth location.
+ EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births.
+ EXPECT_EQ(0u, death_map.size()); // No status yet.
+ // Just like TinyStartupShutdown test.
+ EXPECT_EQ(1u, parent_child_set.size()); // 1 child.
+ EXPECT_EQ(parent_child_set.begin()->first,
+ parent_child_set.begin()->second);
+
+ scoped_ptr<base::Value> value(ThreadData::ToValue(false));
+ std::string json;
+ base::JSONWriter::Write(value.get(), false, &json);
+ std::string birth_only_result = "{"
+ "\"descendants\":["
+ "{"
+ "\"child_location\":{"
+ "\"file_name\":\"FixedUnitTestFileName\","
+ "\"function_name\":\"ParentChildTest\","
+ "\"line_number\":1776"
+ "},"
+ "\"child_thread\":\"WorkerThread-1\","
+ "\"parent_location\":{"
+ "\"file_name\":\"FixedUnitTestFileName\","
+ "\"function_name\":\"ParentChildTest\","
+ "\"line_number\":1776"
+ "},"
+ "\"parent_thread\":\"WorkerThread-1\""
+ "}"
+ "],"
+ "\"list\":["
+ "{"
+ "\"birth_thread\":\"WorkerThread-1\","
+ "\"death_data\":{"
+ "\"count\":2,"
+ "\"queue_ms\":0,"
+ "\"queue_ms_max\":0,"
+ "\"queue_ms_sample\":0,"
+ "\"run_ms\":0,"
+ "\"run_ms_max\":0,"
+ "\"run_ms_sample\":0"
+ "},"
+ "\"death_thread\":\"Still_Alive\","
+ "\"location\":{"
+ "\"file_name\":\"FixedUnitTestFileName\","
+ "\"function_name\":\"ParentChildTest\","
+ "\"line_number\":1776"
+ "}"
+ "}"
+ "]"
+ "}";
+ EXPECT_EQ(json, birth_only_result);
+}
+
TEST_F(TrackedObjectsTest, DeathDataTest) {
if (!ThreadData::InitializeAndSetTrackingStatus(true))
return;
@@ -184,6 +288,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string birth_only_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"]"
"}";
@@ -210,6 +316,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string birth_only_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"]"
"}";
@@ -232,6 +340,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string birth_only_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"WorkerThread-1\","
@@ -274,6 +384,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string birth_only_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"SomeMainThreadName\","
@@ -329,6 +441,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"SomeMainThreadName\","
@@ -391,6 +505,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"SomeMainThreadName\","
@@ -448,6 +564,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"]"
"}";
@@ -481,6 +599,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"WorkerThread-1\","
@@ -517,6 +637,8 @@
value.reset(ThreadData::ToValue(false));
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result_with_zeros = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"WorkerThread-1\","
@@ -580,6 +702,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"SomeFileThreadName\","
@@ -639,6 +763,8 @@
std::string json;
base::JSONWriter::Write(value.get(), false, &json);
std::string one_line_result = "{"
+ "\"descendants\":["
+ "],"
"\"list\":["
"{"
"\"birth_thread\":\"SomeFileThreadName\","