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