OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <set> | 11 #include <set> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "webrtc/base/checks.h" | |
14 #include "webrtc/base/criticalsection.h" | 15 #include "webrtc/base/criticalsection.h" |
15 #include "webrtc/base/event.h" | 16 #include "webrtc/base/event.h" |
16 #include "webrtc/base/gunit.h" | 17 #include "webrtc/base/gunit.h" |
18 #include "webrtc/base/platform_thread.h" | |
17 #include "webrtc/base/scoped_ptr.h" | 19 #include "webrtc/base/scoped_ptr.h" |
18 #include "webrtc/base/scopedptrcollection.h" | 20 #include "webrtc/base/scopedptrcollection.h" |
19 #include "webrtc/base/thread.h" | 21 #include "webrtc/base/thread.h" |
20 | 22 |
21 namespace rtc { | 23 namespace rtc { |
22 | 24 |
23 namespace { | 25 namespace { |
24 | 26 |
25 const int kLongTime = 10000; // 10 seconds | 27 const int kLongTime = 10000; // 10 seconds |
26 const int kNumThreads = 16; | 28 const int kNumThreads = 16; |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 cs.Leave(); | 315 cs.Leave(); |
314 EXPECT_FALSE(cs.IsLocked()); | 316 EXPECT_FALSE(cs.IsLocked()); |
315 if (!cs.TryEnter()) | 317 if (!cs.TryEnter()) |
316 FAIL(); | 318 FAIL(); |
317 EXPECT_TRUE(cs.IsLocked()); | 319 EXPECT_TRUE(cs.IsLocked()); |
318 cs.Leave(); | 320 cs.Leave(); |
319 EXPECT_FALSE(cs.IsLocked()); | 321 EXPECT_FALSE(cs.IsLocked()); |
320 } | 322 } |
321 #endif | 323 #endif |
322 | 324 |
325 class PerfTestData { | |
326 public: | |
327 PerfTestData() : cache_line_barrier_1_(), cache_line_barrier_2_() { | |
328 cache_line_barrier_1_[0]++; // Avoid 'is not used'. | |
329 cache_line_barrier_2_[0]++; // Avoid 'is not used'. | |
330 } | |
331 ~PerfTestData() {} | |
332 | |
333 void AddToCounter(int add) { | |
334 rtc::CritScope cs(&lock_); | |
335 my_counter_ += add; | |
336 } | |
337 | |
338 int64_t total() const { | |
339 // Assume that only one thread is running now. | |
340 return my_counter_; | |
341 } | |
342 | |
343 private: | |
344 uint8_t cache_line_barrier_1_[64]; | |
345 CriticalSection lock_; | |
346 uint8_t cache_line_barrier_2_[64]; | |
347 int64_t my_counter_ = 0; | |
348 }; | |
349 | |
350 class PerfTestThread { | |
351 public: | |
352 PerfTestThread() : thread_(&ThreadFunc, this, "CsPerf") {} | |
353 | |
354 void Start(PerfTestData* data, int repeats, int id) { | |
355 RTC_DCHECK(!thread_.IsRunning()); | |
356 RTC_DCHECK(!data_); | |
357 data_ = data; | |
358 repeats_ = repeats; | |
359 my_id_ = id; | |
360 thread_.Start(); | |
361 } | |
362 | |
363 void Stop() { | |
364 RTC_DCHECK(thread_.IsRunning()); | |
365 RTC_DCHECK(data_); | |
366 thread_.Stop(); | |
367 repeats_ = 0; | |
368 data_ = nullptr; | |
369 my_id_ = 0; | |
370 } | |
371 | |
372 private: | |
373 static bool ThreadFunc(void* param) { | |
374 PerfTestThread* me = static_cast<PerfTestThread*>(param); | |
375 for (int i = 0; i < me->repeats_; ++i) | |
376 me->data_->AddToCounter(me->my_id_); | |
377 return false; | |
378 } | |
379 | |
380 PlatformThread thread_; | |
381 PerfTestData* data_ = nullptr; | |
382 int repeats_ = 0; | |
383 int my_id_ = 0; | |
384 }; | |
385 | |
386 // Comparison of output of this test as tested on a mac laptop: | |
387 // | |
388 // Native mutex implementation: | |
389 // System CPU approx: ~16.16% | |
390 // User mode CPU approx: ~3.4% | |
391 // Unit test output: | |
392 // [ OK ] CriticalSectionTest.Performance (253729 ms) | |
393 // | |
394 // Special partially spin lock based implementation: | |
395 // System CPU approx: ~74% | |
396 // User mode CPU approx: ~18% | |
397 // Unit test output: | |
398 // [ OK ] CriticalSectionTest.Performance (6719 ms) | |
399 // | |
torbjorng (webrtc)
2016/01/21 16:57:23
Cool. You cannot argue with numbers.
Nit: Mentio
tommi
2016/01/21 22:02:47
Done.
| |
400 // The test is disabled by default to avoid unecessarily loading the bots. | |
401 TEST(CriticalSectionTest, DISABLED_Performance) { | |
402 static const int kThreadRepeats = 10000000; | |
403 PerfTestData test_data; | |
404 PerfTestThread threads[8]; | |
405 | |
406 int id = 1; | |
407 int64_t expected_total = 0; | |
408 for (auto& t : threads) { | |
409 expected_total += id * kThreadRepeats; | |
410 t.Start(&test_data, kThreadRepeats, id); | |
411 ++id; | |
412 } | |
413 | |
414 for (auto& t : threads) { | |
415 t.Stop(); | |
416 } | |
417 | |
418 EXPECT_EQ(expected_total, test_data.total()); | |
419 } | |
420 | |
323 } // namespace rtc | 421 } // namespace rtc |
OLD | NEW |