| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/activity_tracker.h" | 5 #include "base/debug/activity_tracker.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file.h" | 10 #include "base/files/file.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 private: | 38 private: |
| 39 std::unique_ptr<char[]> mem_segment_; | 39 std::unique_ptr<char[]> mem_segment_; |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 } // namespace | 42 } // namespace |
| 43 | 43 |
| 44 | 44 |
| 45 class ActivityTrackerTest : public testing::Test { | 45 class ActivityTrackerTest : public testing::Test { |
| 46 public: | 46 public: |
| 47 const int kMemorySize = 1 << 10; // 1MiB | 47 const int kMemorySize = 1 << 20; // 1MiB |
| 48 const int kStackSize = 1 << 10; // 1KiB | 48 const int kStackSize = 1 << 10; // 1KiB |
| 49 | 49 |
| 50 using ActivityId = ThreadActivityTracker::ActivityId; |
| 51 |
| 50 ActivityTrackerTest() {} | 52 ActivityTrackerTest() {} |
| 51 | 53 |
| 52 ~ActivityTrackerTest() override { | 54 ~ActivityTrackerTest() override { |
| 53 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); | 55 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); |
| 54 if (global_tracker) { | 56 if (global_tracker) { |
| 55 global_tracker->ReleaseTrackerForCurrentThreadForTesting(); | 57 global_tracker->ReleaseTrackerForCurrentThreadForTesting(); |
| 56 delete global_tracker; | 58 delete global_tracker; |
| 57 } | 59 } |
| 58 } | 60 } |
| 59 | 61 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 71 } | 73 } |
| 72 | 74 |
| 73 size_t GetGlobalInactiveTrackerCount() { | 75 size_t GetGlobalInactiveTrackerCount() { |
| 74 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); | 76 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); |
| 75 if (!global_tracker) | 77 if (!global_tracker) |
| 76 return 0; | 78 return 0; |
| 77 base::AutoLock autolock(global_tracker->thread_tracker_allocator_lock_); | 79 base::AutoLock autolock(global_tracker->thread_tracker_allocator_lock_); |
| 78 return global_tracker->thread_tracker_allocator_.cache_used(); | 80 return global_tracker->thread_tracker_allocator_.cache_used(); |
| 79 } | 81 } |
| 80 | 82 |
| 83 size_t GetGlobalUserDataMemoryCacheUsed() { |
| 84 return GlobalActivityTracker::Get()->user_data_allocator_.cache_used(); |
| 85 } |
| 86 |
| 81 static void DoNothing() {} | 87 static void DoNothing() {} |
| 82 }; | 88 }; |
| 83 | 89 |
| 90 TEST_F(ActivityTrackerTest, UserDataTest) { |
| 91 char buffer[256]; |
| 92 memset(buffer, 0, sizeof(buffer)); |
| 93 ActivityUserData data(buffer, sizeof(buffer)); |
| 94 ASSERT_EQ(sizeof(buffer), data.available_); |
| 95 |
| 96 data.SetInt("foo", 1); |
| 97 ASSERT_EQ(sizeof(buffer) - 24, data.available_); |
| 98 |
| 99 data.SetUint("b", 1U); // Small names fit beside header in a word. |
| 100 ASSERT_EQ(sizeof(buffer) - 24 - 16, data.available_); |
| 101 |
| 102 data.Set("c", buffer, 10); |
| 103 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24, data.available_); |
| 104 |
| 105 data.SetString("dear john", "it's been fun"); |
| 106 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24 - 32, data.available_); |
| 107 |
| 108 data.Set("c", buffer, 20); |
| 109 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24 - 32, data.available_); |
| 110 |
| 111 data.SetString("dear john", "but we're done together"); |
| 112 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24 - 32, data.available_); |
| 113 |
| 114 data.SetString("dear john", "bye"); |
| 115 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24 - 32, data.available_); |
| 116 |
| 117 data.SetChar("d", 'x'); |
| 118 ASSERT_EQ(sizeof(buffer) - 24 - 16 - 24 - 32 - 16, data.available_); |
| 119 } |
| 120 |
| 84 TEST_F(ActivityTrackerTest, PushPopTest) { | 121 TEST_F(ActivityTrackerTest, PushPopTest) { |
| 85 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker(); | 122 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker(); |
| 86 ActivitySnapshot snapshot; | 123 ActivitySnapshot snapshot; |
| 87 | 124 |
| 88 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 125 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 89 ASSERT_EQ(0U, snapshot.activity_stack_depth); | 126 ASSERT_EQ(0U, snapshot.activity_stack_depth); |
| 90 ASSERT_EQ(0U, snapshot.activity_stack.size()); | 127 ASSERT_EQ(0U, snapshot.activity_stack.size()); |
| 91 | 128 |
| 92 char origin1; | 129 char origin1; |
| 93 tracker->PushActivity(&origin1, Activity::ACT_TASK, | 130 ActivityId id1 = tracker->PushActivity(&origin1, Activity::ACT_TASK, |
| 94 ActivityData::ForTask(11)); | 131 ActivityData::ForTask(11)); |
| 95 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 132 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 96 ASSERT_EQ(1U, snapshot.activity_stack_depth); | 133 ASSERT_EQ(1U, snapshot.activity_stack_depth); |
| 97 ASSERT_EQ(1U, snapshot.activity_stack.size()); | 134 ASSERT_EQ(1U, snapshot.activity_stack.size()); |
| 98 EXPECT_NE(0, snapshot.activity_stack[0].time_internal); | 135 EXPECT_NE(0, snapshot.activity_stack[0].time_internal); |
| 99 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); | 136 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); |
| 100 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1), | 137 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1), |
| 101 snapshot.activity_stack[0].origin_address); | 138 snapshot.activity_stack[0].origin_address); |
| 102 EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id); | 139 EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id); |
| 103 | 140 |
| 104 char origin2; | 141 char origin2; |
| 105 char lock2; | 142 char lock2; |
| 106 tracker->PushActivity(&origin2, Activity::ACT_LOCK, | 143 ActivityId id2 = tracker->PushActivity(&origin2, Activity::ACT_LOCK, |
| 107 ActivityData::ForLock(&lock2)); | 144 ActivityData::ForLock(&lock2)); |
| 108 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 145 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 109 ASSERT_EQ(2U, snapshot.activity_stack_depth); | 146 ASSERT_EQ(2U, snapshot.activity_stack_depth); |
| 110 ASSERT_EQ(2U, snapshot.activity_stack.size()); | 147 ASSERT_EQ(2U, snapshot.activity_stack.size()); |
| 111 EXPECT_LE(snapshot.activity_stack[0].time_internal, | 148 EXPECT_LE(snapshot.activity_stack[0].time_internal, |
| 112 snapshot.activity_stack[1].time_internal); | 149 snapshot.activity_stack[1].time_internal); |
| 113 EXPECT_EQ(Activity::ACT_LOCK, snapshot.activity_stack[1].activity_type); | 150 EXPECT_EQ(Activity::ACT_LOCK, snapshot.activity_stack[1].activity_type); |
| 114 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin2), | 151 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin2), |
| 115 snapshot.activity_stack[1].origin_address); | 152 snapshot.activity_stack[1].origin_address); |
| 116 EXPECT_EQ(reinterpret_cast<uintptr_t>(&lock2), | 153 EXPECT_EQ(reinterpret_cast<uintptr_t>(&lock2), |
| 117 snapshot.activity_stack[1].data.lock.lock_address); | 154 snapshot.activity_stack[1].data.lock.lock_address); |
| 118 | 155 |
| 119 tracker->PopActivity(); | 156 tracker->PopActivity(id2); |
| 120 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 157 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 121 ASSERT_EQ(1U, snapshot.activity_stack_depth); | 158 ASSERT_EQ(1U, snapshot.activity_stack_depth); |
| 122 ASSERT_EQ(1U, snapshot.activity_stack.size()); | 159 ASSERT_EQ(1U, snapshot.activity_stack.size()); |
| 123 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); | 160 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); |
| 124 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1), | 161 EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1), |
| 125 snapshot.activity_stack[0].origin_address); | 162 snapshot.activity_stack[0].origin_address); |
| 126 EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id); | 163 EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id); |
| 127 | 164 |
| 128 tracker->PopActivity(); | 165 tracker->PopActivity(id1); |
| 129 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 166 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 130 ASSERT_EQ(0U, snapshot.activity_stack_depth); | 167 ASSERT_EQ(0U, snapshot.activity_stack_depth); |
| 131 ASSERT_EQ(0U, snapshot.activity_stack.size()); | 168 ASSERT_EQ(0U, snapshot.activity_stack.size()); |
| 132 } | 169 } |
| 133 | 170 |
| 134 TEST_F(ActivityTrackerTest, ScopedTaskTest) { | 171 TEST_F(ActivityTrackerTest, ScopedTaskTest) { |
| 135 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3); | 172 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3); |
| 136 | 173 |
| 137 ThreadActivityTracker* tracker = | 174 ThreadActivityTracker* tracker = |
| 138 GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread(); | 175 GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread(); |
| 139 ActivitySnapshot snapshot; | 176 ActivitySnapshot snapshot; |
| 177 ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed()); |
| 140 | 178 |
| 141 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 179 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 142 ASSERT_EQ(0U, snapshot.activity_stack_depth); | 180 ASSERT_EQ(0U, snapshot.activity_stack_depth); |
| 143 ASSERT_EQ(0U, snapshot.activity_stack.size()); | 181 ASSERT_EQ(0U, snapshot.activity_stack.size()); |
| 144 | 182 |
| 145 { | 183 { |
| 146 PendingTask task1(FROM_HERE, base::Bind(&DoNothing)); | 184 PendingTask task1(FROM_HERE, base::Bind(&DoNothing)); |
| 147 ScopedTaskRunActivity activity1(task1); | 185 ScopedTaskRunActivity activity1(task1); |
| 186 ActivityUserData& user_data1 = activity1.user_data(); |
| 187 (void)user_data1; // Tell compiler it's been used. |
| 148 | 188 |
| 149 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 189 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 150 ASSERT_EQ(1U, snapshot.activity_stack_depth); | 190 ASSERT_EQ(1U, snapshot.activity_stack_depth); |
| 151 ASSERT_EQ(1U, snapshot.activity_stack.size()); | 191 ASSERT_EQ(1U, snapshot.activity_stack.size()); |
| 152 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); | 192 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); |
| 153 | 193 |
| 154 { | 194 { |
| 155 PendingTask task2(FROM_HERE, base::Bind(&DoNothing)); | 195 PendingTask task2(FROM_HERE, base::Bind(&DoNothing)); |
| 156 ScopedTaskRunActivity activity2(task2); | 196 ScopedTaskRunActivity activity2(task2); |
| 197 ActivityUserData& user_data2 = activity2.user_data(); |
| 198 (void)user_data2; // Tell compiler it's been used. |
| 157 | 199 |
| 158 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 200 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 159 ASSERT_EQ(2U, snapshot.activity_stack_depth); | 201 ASSERT_EQ(2U, snapshot.activity_stack_depth); |
| 160 ASSERT_EQ(2U, snapshot.activity_stack.size()); | 202 ASSERT_EQ(2U, snapshot.activity_stack.size()); |
| 161 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[1].activity_type); | 203 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[1].activity_type); |
| 162 } | 204 } |
| 163 | 205 |
| 164 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 206 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 165 ASSERT_EQ(1U, snapshot.activity_stack_depth); | 207 ASSERT_EQ(1U, snapshot.activity_stack_depth); |
| 166 ASSERT_EQ(1U, snapshot.activity_stack.size()); | 208 ASSERT_EQ(1U, snapshot.activity_stack.size()); |
| 167 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); | 209 EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type); |
| 168 } | 210 } |
| 169 | 211 |
| 170 ASSERT_TRUE(tracker->Snapshot(&snapshot)); | 212 ASSERT_TRUE(tracker->Snapshot(&snapshot)); |
| 171 ASSERT_EQ(0U, snapshot.activity_stack_depth); | 213 ASSERT_EQ(0U, snapshot.activity_stack_depth); |
| 172 ASSERT_EQ(0U, snapshot.activity_stack.size()); | 214 ASSERT_EQ(0U, snapshot.activity_stack.size()); |
| 215 ASSERT_EQ(2U, GetGlobalUserDataMemoryCacheUsed()); |
| 173 } | 216 } |
| 174 | 217 |
| 175 TEST_F(ActivityTrackerTest, CreateWithFileTest) { | 218 TEST_F(ActivityTrackerTest, CreateWithFileTest) { |
| 176 const char temp_name[] = "CreateWithFileTest"; | 219 const char temp_name[] = "CreateWithFileTest"; |
| 177 ScopedTempDir temp_dir; | 220 ScopedTempDir temp_dir; |
| 178 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 221 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 179 FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name); | 222 FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name); |
| 180 const size_t temp_size = 64 << 10; // 64 KiB | 223 const size_t temp_size = 64 << 10; // 64 KiB |
| 181 | 224 |
| 182 // Create a global tracker on a new file. | 225 // Create a global tracker on a new file. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 208 const ActivityData& data) | 251 const ActivityData& data) |
| 209 : SimpleThread(name, Options()), | 252 : SimpleThread(name, Options()), |
| 210 origin_(origin), | 253 origin_(origin), |
| 211 activity_(activity), | 254 activity_(activity), |
| 212 data_(data), | 255 data_(data), |
| 213 exit_condition_(&lock_) {} | 256 exit_condition_(&lock_) {} |
| 214 | 257 |
| 215 ~SimpleActivityThread() override {} | 258 ~SimpleActivityThread() override {} |
| 216 | 259 |
| 217 void Run() override { | 260 void Run() override { |
| 218 GlobalActivityTracker::Get() | 261 ThreadActivityTracker::ActivityId id = |
| 219 ->GetOrCreateTrackerForCurrentThread() | 262 GlobalActivityTracker::Get() |
| 220 ->PushActivity(origin_, activity_, data_); | 263 ->GetOrCreateTrackerForCurrentThread() |
| 264 ->PushActivity(origin_, activity_, data_); |
| 221 | 265 |
| 222 { | 266 { |
| 223 AutoLock auto_lock(lock_); | 267 AutoLock auto_lock(lock_); |
| 224 ready_ = true; | 268 ready_ = true; |
| 225 while (!exit_) | 269 while (!exit_) |
| 226 exit_condition_.Wait(); | 270 exit_condition_.Wait(); |
| 227 } | 271 } |
| 228 | 272 |
| 229 GlobalActivityTracker::Get() | 273 GlobalActivityTracker::Get()->GetTrackerForCurrentThread()->PopActivity(id); |
| 230 ->GetOrCreateTrackerForCurrentThread() | |
| 231 ->PopActivity(); | |
| 232 } | 274 } |
| 233 | 275 |
| 234 void Exit() { | 276 void Exit() { |
| 235 AutoLock auto_lock(lock_); | 277 AutoLock auto_lock(lock_); |
| 236 exit_ = true; | 278 exit_ = true; |
| 237 exit_condition_.Signal(); | 279 exit_condition_.Signal(); |
| 238 } | 280 } |
| 239 | 281 |
| 240 void WaitReady() { | 282 void WaitReady() { |
| 241 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_); | 283 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount()); | 324 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount()); |
| 283 | 325 |
| 284 t2.Exit(); | 326 t2.Exit(); |
| 285 t2.Join(); | 327 t2.Join(); |
| 286 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount()); | 328 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount()); |
| 287 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount()); | 329 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount()); |
| 288 } | 330 } |
| 289 | 331 |
| 290 } // namespace debug | 332 } // namespace debug |
| 291 } // namespace base | 333 } // namespace base |
| OLD | NEW |