| Index: webrtc/base/criticalsection_unittest.cc
|
| diff --git a/webrtc/base/criticalsection_unittest.cc b/webrtc/base/criticalsection_unittest.cc
|
| index d6990c0023d8b02a33a97abdfce4da99ded00bc4..a0e103386280dbfd8cef4e5d8c2bd0fe1beb0f60 100644
|
| --- a/webrtc/base/criticalsection_unittest.cc
|
| +++ b/webrtc/base/criticalsection_unittest.cc
|
| @@ -11,9 +11,12 @@
|
| #include <set>
|
| #include <vector>
|
|
|
| +#include "webrtc/base/arraysize.h"
|
| +#include "webrtc/base/checks.h"
|
| #include "webrtc/base/criticalsection.h"
|
| #include "webrtc/base/event.h"
|
| #include "webrtc/base/gunit.h"
|
| +#include "webrtc/base/platform_thread.h"
|
| #include "webrtc/base/scoped_ptr.h"
|
| #include "webrtc/base/scopedptrcollection.h"
|
| #include "webrtc/base/thread.h"
|
| @@ -320,4 +323,109 @@ TEST(CriticalSectionTest, IsLocked) {
|
| }
|
| #endif
|
|
|
| +class PerfTestData {
|
| + public:
|
| + PerfTestData(int expected_count, Event* event)
|
| + : cache_line_barrier_1_(), cache_line_barrier_2_(),
|
| + expected_count_(expected_count), event_(event) {
|
| + cache_line_barrier_1_[0]++; // Avoid 'is not used'.
|
| + cache_line_barrier_2_[0]++; // Avoid 'is not used'.
|
| + }
|
| + ~PerfTestData() {}
|
| +
|
| + void AddToCounter(int add) {
|
| + rtc::CritScope cs(&lock_);
|
| + my_counter_ += add;
|
| + if (my_counter_ == expected_count_)
|
| + event_->Set();
|
| + }
|
| +
|
| + int64_t total() const {
|
| + // Assume that only one thread is running now.
|
| + return my_counter_;
|
| + }
|
| +
|
| + private:
|
| + uint8_t cache_line_barrier_1_[64];
|
| + CriticalSection lock_;
|
| + uint8_t cache_line_barrier_2_[64];
|
| + int64_t my_counter_ = 0;
|
| + const int expected_count_;
|
| + Event* const event_;
|
| +};
|
| +
|
| +class PerfTestThread {
|
| + public:
|
| + PerfTestThread() : thread_(&ThreadFunc, this, "CsPerf") {}
|
| +
|
| + void Start(PerfTestData* data, int repeats, int id) {
|
| + RTC_DCHECK(!thread_.IsRunning());
|
| + RTC_DCHECK(!data_);
|
| + data_ = data;
|
| + repeats_ = repeats;
|
| + my_id_ = id;
|
| + thread_.Start();
|
| + }
|
| +
|
| + void Stop() {
|
| + RTC_DCHECK(thread_.IsRunning());
|
| + RTC_DCHECK(data_);
|
| + thread_.Stop();
|
| + repeats_ = 0;
|
| + data_ = nullptr;
|
| + my_id_ = 0;
|
| + }
|
| +
|
| + private:
|
| + static bool ThreadFunc(void* param) {
|
| + PerfTestThread* me = static_cast<PerfTestThread*>(param);
|
| + for (int i = 0; i < me->repeats_; ++i)
|
| + me->data_->AddToCounter(me->my_id_);
|
| + return false;
|
| + }
|
| +
|
| + PlatformThread thread_;
|
| + PerfTestData* data_ = nullptr;
|
| + int repeats_ = 0;
|
| + int my_id_ = 0;
|
| +};
|
| +
|
| +// Comparison of output of this test as tested on a MacBook Pro Retina, 15-inch,
|
| +// Mid 2014, 2,8 GHz Intel Core i7, 16 GB 1600 MHz DDR3,
|
| +// running OS X El Capitan, 10.11.2.
|
| +//
|
| +// Native mutex implementation:
|
| +// Approximate CPU usage:
|
| +// System: ~16%
|
| +// User mode: ~1.3%
|
| +// Idle: ~82%
|
| +// Unit test output:
|
| +// [ OK ] CriticalSectionTest.Performance (234545 ms)
|
| +//
|
| +// Special partially spin lock based implementation:
|
| +// Approximate CPU usage:
|
| +// System: ~75%
|
| +// User mode: ~16%
|
| +// Idle: ~8%
|
| +// Unit test output:
|
| +// [ OK ] CriticalSectionTest.Performance (2107 ms)
|
| +//
|
| +// The test is disabled by default to avoid unecessarily loading the bots.
|
| +TEST(CriticalSectionTest, DISABLED_Performance) {
|
| + PerfTestThread threads[8];
|
| + Event event(false, false);
|
| +
|
| + static const int kThreadRepeats = 10000000;
|
| + static const int kExpectedCount = kThreadRepeats * arraysize(threads);
|
| + PerfTestData test_data(kExpectedCount, &event);
|
| +
|
| + for (auto& t : threads)
|
| + t.Start(&test_data, kThreadRepeats, 1);
|
| +
|
| + event.Wait(Event::kForever);
|
| +
|
| + for (auto& t : threads)
|
| + t.Stop();
|
| +}
|
| +
|
| } // namespace rtc
|
|
|