Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: base/debug/activity_tracker_unittest.cc

Issue 2255503002: New cache for the activity tracker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: refactor fifo (now queue) to allocate slot before updating it Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/files/memory_mapped_file.h" 12 #include "base/files/memory_mapped_file.h"
13 #include "base/files/scoped_temp_dir.h" 13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/pending_task.h" 15 #include "base/pending_task.h"
16 #include "base/rand_util.h"
16 #include "base/synchronization/condition_variable.h" 17 #include "base/synchronization/condition_variable.h"
17 #include "base/synchronization/lock.h" 18 #include "base/synchronization/lock.h"
18 #include "base/synchronization/spin_wait.h" 19 #include "base/synchronization/spin_wait.h"
20 #include "base/threading/platform_thread.h"
19 #include "base/threading/simple_thread.h" 21 #include "base/threading/simple_thread.h"
20 #include "base/time/time.h" 22 #include "base/time/time.h"
21 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
22 24
23 namespace base { 25 namespace base {
24 namespace debug { 26 namespace debug {
25 27
26 namespace { 28 namespace {
27 29
28 class TestActivityTracker : public ThreadActivityTracker { 30 class TestActivityTracker : public ThreadActivityTracker {
29 public: 31 public:
30 TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size) 32 TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size)
31 : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size), 33 : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size),
32 mem_segment_(std::move(memory)) {} 34 mem_segment_(std::move(memory)) {}
33 35
34 ~TestActivityTracker() override {} 36 ~TestActivityTracker() override {}
35 37
36 private: 38 private:
37 std::unique_ptr<char[]> mem_segment_; 39 std::unique_ptr<char[]> mem_segment_;
38 }; 40 };
39 41
42
43 // The interval between which the Queue threads will wait for the queue to
44 // become full or empty. It's prime so that it won't correspond to any other
45 // interval (except itself).
46 const int kQueueTestOperationInterval = 997;
47
48 class QueuePushThread : public SimpleThread {
49 public:
50 QueuePushThread(LockFreeSimpleQueue<int>* queue, int count)
51 : SimpleThread("QueuePush", Options()), queue_(queue), count_(count) {}
52 ~QueuePushThread() override {}
53
54 void Run() override {
55 int yield_after = RandInt(1, queue_->size() * 2);
56 for (int i = 0; i < count_; ++i) {
57 // Two ways of pushing: check for full first or check for failed push.
58 if (i % 1 == 0) {
manzagop (departed) 2016/08/23 16:02:03 This is always true?
bcwhite 2016/08/23 16:12:41 Fixed. I had changed in while testing the test an
59 // Will fail if full; keep trying.
60 while (!queue_->push(i))
61 ;
62 } else {
63 // This is valid because there is exactly one thread pushing.
64 while (queue_->full())
65 ;
66 DCHECK(queue_->push(i));
67 }
68
69 // Take a break once in a while.
70 if (--yield_after <= 0) {
71 PlatformThread::YieldCurrentThread();
72 yield_after = RandInt(1, queue_->size() * 2);
73 }
74
75 // Every so often, wait for the queue to empty.
76 if (i < count_ - kQueueTestOperationInterval &&
77 i % kQueueTestOperationInterval == kQueueTestOperationInterval - 1) {
78 while (!queue_->empty())
manzagop (departed) 2016/08/23 16:02:03 Is it guaranteed that the popper is still alive? S
bcwhite 2016/08/23 16:12:41 There's no protection against thread-death in the
manzagop (departed) 2016/08/23 19:46:08 Ah, what I meant is could it have exited already,
bcwhite 2016/08/23 20:16:46 Acknowledged.
79 ;
80 }
81 }
82 }
83
84 private:
85 LockFreeSimpleQueue<int>* const queue_;
86 const int count_;
87
88 DISALLOW_COPY_AND_ASSIGN(QueuePushThread);
89 };
90
91 class QueuePopThread : public SimpleThread {
92 public:
93 QueuePopThread(LockFreeSimpleQueue<int>* queue, int count)
94 : SimpleThread("QueuePop", Options()), queue_(queue), count_(count) {}
95 ~QueuePopThread() override {}
96
97 void Run() override {
98 int yield_after = RandInt(1, queue_->size() * 2);
99 for (int i = 0; i < count_; ++i) {
100 int popped;
101 // Two ways of popping: check for empty first or check for invalid return.
102 if (i % 2 == 0) {
103 // Will return "invalid" if empty; keep trying.
104 while ((popped = queue_->pop()) < 0)
105 ;
106 } else {
107 // This is valid only because there is exactly one thread popping.
108 while (queue_->empty())
109 ;
110 popped = queue_->pop();
111 }
112 DCHECK_EQ(i, popped);
113
114 // Take a break once in a while.
115 if (--yield_after <= 0) {
116 PlatformThread::YieldCurrentThread();
117 yield_after = RandInt(1, queue_->size() * 2);
118 }
119
120 // Every so often, wait for the queue to fill.
121 if (i < count_ - kQueueTestOperationInterval &&
122 i % kQueueTestOperationInterval == kQueueTestOperationInterval / 2) {
123 while (!queue_->full())
124 ;
125 }
126 }
127 }
128
129 private:
130 LockFreeSimpleQueue<int>* const queue_;
131 const int count_;
132
133 DISALLOW_COPY_AND_ASSIGN(QueuePopThread);
134 };
135
40 } // namespace 136 } // namespace
41 137
42 138
139 TEST(LockFreeSimpleQueue, PushPopTest) {
140 LockFreeSimpleQueue<int> queue(50U, -1);
141 ASSERT_EQ(50U, queue.size());
142 ASSERT_EQ(0U, queue.used());
143
144 queue.push(1001);
145 EXPECT_EQ(1U, queue.used());
146
147 queue.push(2002);
148 EXPECT_EQ(2U, queue.used());
149
150 int value = queue.pop();
151 EXPECT_EQ(1001, value);
152 EXPECT_EQ(1U, queue.used());
153
154 value = queue.pop();
155 EXPECT_EQ(2002, value);
156 EXPECT_EQ(0U, queue.used());
157
158 value = queue.pop();
159 ASSERT_EQ(-1, value);
160 ASSERT_TRUE(queue.empty());
161
162 // Test push/pop many times and in parallel.
163 const int kQueueOperations = 1000000;
164 QueuePushThread pusher(&queue, kQueueOperations);
165 QueuePopThread popper(&queue, kQueueOperations);
166 pusher.Start();
167 popper.Start();
168 pusher.Join();
169 popper.Join();
170 }
171
172
43 class ActivityTrackerTest : public testing::Test { 173 class ActivityTrackerTest : public testing::Test {
44 public: 174 public:
45 const int kMemorySize = 1 << 10; // 1MiB 175 const int kMemorySize = 1 << 10; // 1MiB
46 const int kStackSize = 1 << 10; // 1KiB 176 const int kStackSize = 1 << 10; // 1KiB
47 177
48 ActivityTrackerTest() {} 178 ActivityTrackerTest() {}
49 179
50 ~ActivityTrackerTest() override { 180 ~ActivityTrackerTest() override {
51 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); 181 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
52 if (global_tracker) { 182 if (global_tracker) {
(...skipping 12 matching lines...) Expand all
65 if (!global_tracker) 195 if (!global_tracker)
66 return 0; 196 return 0;
67 return global_tracker->thread_tracker_count_.load( 197 return global_tracker->thread_tracker_count_.load(
68 std::memory_order_relaxed); 198 std::memory_order_relaxed);
69 } 199 }
70 200
71 size_t GetGlobalInactiveTrackerCount() { 201 size_t GetGlobalInactiveTrackerCount() {
72 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); 202 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
73 if (!global_tracker) 203 if (!global_tracker)
74 return 0; 204 return 0;
75 return global_tracker->available_memories_count_.load( 205 return global_tracker->available_memories_.used();
76 std::memory_order_relaxed);
77 } 206 }
78 207
79 static void DoNothing() {} 208 static void DoNothing() {}
80 }; 209 };
81 210
82 TEST_F(ActivityTrackerTest, PushPopTest) { 211 TEST_F(ActivityTrackerTest, PushPopTest) {
83 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker(); 212 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
84 ActivitySnapshot snapshot; 213 ActivitySnapshot snapshot;
85 214
86 ASSERT_TRUE(tracker->Snapshot(&snapshot)); 215 ASSERT_TRUE(tracker->Snapshot(&snapshot));
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount()); 409 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
281 410
282 t2.Exit(); 411 t2.Exit();
283 t2.Join(); 412 t2.Join();
284 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount()); 413 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
285 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount()); 414 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
286 } 415 }
287 416
288 } // namespace debug 417 } // namespace debug
289 } // namespace base 418 } // namespace base
OLDNEW
« base/debug/activity_tracker.h ('K') | « base/debug/activity_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698