Index: webrtc/base/criticalsection_unittest.cc |
diff --git a/webrtc/base/criticalsection_unittest.cc b/webrtc/base/criticalsection_unittest.cc |
index d6990c0023d8b02a33a97abdfce4da99ded00bc4..1bd7deeac1c8d6ccd9668dfecc0b044bc1f7e558 100644 |
--- a/webrtc/base/criticalsection_unittest.cc |
+++ b/webrtc/base/criticalsection_unittest.cc |
@@ -11,9 +11,11 @@ |
#include <set> |
#include <vector> |
+#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 +322,100 @@ TEST(CriticalSectionTest, IsLocked) { |
} |
#endif |
+class PerfTestData { |
+ public: |
+ PerfTestData() : cache_line_barrier_1_(), cache_line_barrier_2_() { |
+ 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; |
+ } |
+ |
+ 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; |
+}; |
+ |
+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 mac laptop: |
+// |
+// Native mutex implementation: |
+// System CPU approx: ~16.16% |
+// User mode CPU approx: ~3.4% |
+// Unit test output: |
+// [ OK ] CriticalSectionTest.Performance (253729 ms) |
+// |
+// Special partially spin lock based implementation: |
+// System CPU approx: ~74% |
+// User mode CPU approx: ~18% |
+// Unit test output: |
+// [ OK ] CriticalSectionTest.Performance (6719 ms) |
+// |
torbjorng (webrtc)
2016/01/21 16:57:23
Cool. You cannot argue with numbers.
Nit: Mentio
tommi
2016/01/21 22:02:47
Done.
|
+// The test is disabled by default to avoid unecessarily loading the bots. |
+TEST(CriticalSectionTest, DISABLED_Performance) { |
+ static const int kThreadRepeats = 10000000; |
+ PerfTestData test_data; |
+ PerfTestThread threads[8]; |
+ |
+ int id = 1; |
+ int64_t expected_total = 0; |
+ for (auto& t : threads) { |
+ expected_total += id * kThreadRepeats; |
+ t.Start(&test_data, kThreadRepeats, id); |
+ ++id; |
+ } |
+ |
+ for (auto& t : threads) { |
+ t.Stop(); |
+ } |
+ |
+ EXPECT_EQ(expected_total, test_data.total()); |
+} |
+ |
} // namespace rtc |