1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/android/orderfile/orderfile_instrumentation.h"
6
7 #include <thread>
8
9 #include "base/android/library_loader/anchor_functions.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/perf/perf_test.h"
14
15 namespace base {
16 namespace android {
17 namespace orderfile {
18
19 namespace {
20
21 // Records |addresses_count| distinct addresses |iterations| times, in
22 // |threads|.
RunBenchmark(int iterations,int addresses_count,int threads)23 void RunBenchmark(int iterations, int addresses_count, int threads) {
24 ResetForTesting();
25 auto iterate = [iterations, addresses_count]() {
26 for (int i = 0; i < iterations; i++) {
27 for (size_t addr = kStartOfTextForTesting;
28 addr < static_cast<size_t>(addresses_count); addr += sizeof(int)) {
29 RecordAddressForTesting(addr);
30 }
31 }
32 };
33 if (threads != 1) {
34 for (int i = 0; i < threads - 1; ++i)
35 std::thread(iterate).detach();
36 }
37 auto tick = base::TimeTicks::Now();
38 iterate();
39 auto tock = base::TimeTicks::Now();
40 double nanos = static_cast<double>((tock - tick).InNanoseconds());
41 auto ns_per_call =
42 nanos / (iterations * static_cast<double>(addresses_count));
43 auto modifier =
44 base::StringPrintf("_%d_%d_%d", iterations, addresses_count, threads);
45 perf_test::PrintResult("RecordAddressCostPerCall", modifier, "", ns_per_call,
46 "ns", true);
47 }
48
49 } // namespace
50
51 class OrderfileInstrumentationTest : public ::testing::Test {
52 // Any tests need to run ResetForTesting() when they start. Because this
53 // perftest is built with instrumentation enabled, all code including
54 // ::testing::Test is instrumented. If ResetForTesting() is called earlier,
55 // for example in setUp(), any test harness code between setUp() and the
56 // actual test will change the instrumentation offset record in unpredictable
57 // ways and make these tests unreliable.
58 };
59
TEST_F(OrderfileInstrumentationTest,RecordOffset)60 TEST_F(OrderfileInstrumentationTest, RecordOffset) {
61 ResetForTesting();
62 size_t first = 1234, second = 1456;
63 RecordAddressForTesting(first);
64 RecordAddressForTesting(second);
65 RecordAddressForTesting(first); // No duplicates.
66 RecordAddressForTesting(first + 1); // 4 bytes granularity.
67 Disable();
68
69 auto reached = GetOrderedOffsetsForTesting();
70 EXPECT_EQ(2UL, reached.size());
71 EXPECT_EQ(first - kStartOfTextForTesting, reached[0]);
72 EXPECT_EQ(second - kStartOfTextForTesting, reached[1]);
73 }
74
TEST_F(OrderfileInstrumentationTest,RecordingStops)75 TEST_F(OrderfileInstrumentationTest, RecordingStops) {
76 ResetForTesting();
77 size_t first = 1234, second = 1456, third = 1789;
78 RecordAddressForTesting(first);
79 RecordAddressForTesting(second);
80 Disable();
81 RecordAddressForTesting(third);
82
83 auto reached = GetOrderedOffsetsForTesting();
84 ASSERT_EQ(2UL, reached.size());
85 ASSERT_EQ(first - kStartOfTextForTesting, reached[0]);
86 ASSERT_EQ(second - kStartOfTextForTesting, reached[1]);
87 }
88
TEST_F(OrderfileInstrumentationTest,OutOfBounds)89 TEST_F(OrderfileInstrumentationTest, OutOfBounds) {
90 ResetForTesting();
91 EXPECT_DEATH(RecordAddressForTesting(kEndOfTextForTesting + 100), "");
92 EXPECT_DEATH(RecordAddressForTesting(kStartOfTextForTesting - 100), "");
93 }
94
TEST(OrderfileInstrumentationPerfTest,RecordAddress_10_10000)95 TEST(OrderfileInstrumentationPerfTest, RecordAddress_10_10000) {
96 RunBenchmark(10, 10000, 1);
97 }
98
TEST(OrderfileInstrumentationPerfTest,RecordAddress_100_10000)99 TEST(OrderfileInstrumentationPerfTest, RecordAddress_100_10000) {
100 RunBenchmark(100, 10000, 1);
101 }
102
TEST(OrderfileInstrumentationPerfTest,RecordAddress_10_100000)103 TEST(OrderfileInstrumentationPerfTest, RecordAddress_10_100000) {
104 RunBenchmark(10, 100000, 1);
105 }
106
TEST(OrderfileInstrumentationPerfTest,RecordAddress_100_100000)107 TEST(OrderfileInstrumentationPerfTest, RecordAddress_100_100000) {
108 RunBenchmark(100, 100000, 1);
109 }
110
TEST(OrderfileInstrumentationPerfTest,RecordAddress_1000_100000_2)111 TEST(OrderfileInstrumentationPerfTest, RecordAddress_1000_100000_2) {
112 RunBenchmark(1000, 100000, 2);
113 }
114
TEST(OrderfileInstrumentationPerfTest,RecordAddress_1000_100000_3)115 TEST(OrderfileInstrumentationPerfTest, RecordAddress_1000_100000_3) {
116 RunBenchmark(1000, 100000, 3);
117 }
118
TEST(OrderfileInstrumentationPerfTest,RecordAddress_1000_100000_4)119 TEST(OrderfileInstrumentationPerfTest, RecordAddress_1000_100000_4) {
120 RunBenchmark(1000, 100000, 4);
121 }
122
TEST(OrderfileInstrumentationPerfTest,RecordAddress_1000_100000_6)123 TEST(OrderfileInstrumentationPerfTest, RecordAddress_1000_100000_6) {
124 RunBenchmark(1000, 100000, 6);
125 }
126
127 } // namespace orderfile
128 } // namespace android
129 } // namespace base
130
131 // Custom runner implementation since base's one requires JNI on Android.
main(int argc,char ** argv)132 int main(int argc, char** argv) {
133 testing::InitGoogleTest(&argc, argv);
134 return RUN_ALL_TESTS();
135 }
136