• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "perf_events_test.h"
17 
18 #include <chrono>
19 #include <cinttypes>
20 #include <cstdlib>
21 #include <thread>
22 #include <unistd.h>
23 
24 #include "debug_logger.h"
25 #include "utilities.h"
26 
27 using namespace testing::ext;
28 using namespace std;
29 using namespace OHOS::HiviewDFX;
30 
31 namespace OHOS {
32 namespace Developtools {
33 namespace HiPerf {
34 class PerfEventsTest : public testing::Test {
35 public:
36     static void SetUpTestCase(void);
37     static void TearDownTestCase(void);
38     void SetUp();
39     void TearDown();
40 
41     static void TestCodeThread(void);
42     static void RunTestThreads(std::vector<std::thread> &threads);
43     static void SetAllConfig(PerfEvents &event);
44     static bool RecordCount(std::unique_ptr<PerfEventRecord> record);
45     static void StatCount(
46         const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
47 
48     static constexpr int TEST_CODE_MEM_FILE_SIZE = 1024;
49     static constexpr auto TEST_CODE_SLEEP_BEFORE_RUN = 500ms;
50     static constexpr auto TEST_CODE_SLEEP_AFTER_RUN = 1000ms;
51     static constexpr int TEST_CODE_RUN_TIME = 10240;
52     static constexpr int DOUBLE = 2;
53     static constexpr int TRIPLE = 3;
54     static constexpr auto TEST_TIME = 3s;
55     static constexpr auto DEFAULT_TRACKING_TIME = 1000;
56     static constexpr auto DEFAULT_STAT_REPORT_TIME = 500;
57     static constexpr auto DEFAULT_SAMPLE_MMAPAGE = 256;
58 
59     static uint64_t g_recordCount;
60     static uint64_t g_statCount;
61 };
62 
SetUpTestCase()63 void PerfEventsTest::SetUpTestCase() {}
64 
TearDownTestCase()65 void PerfEventsTest::TearDownTestCase() {}
66 
SetUp()67 void PerfEventsTest::SetUp() {}
68 
TearDown()69 void PerfEventsTest::TearDown() {}
70 
71 uint64_t PerfEventsTest::g_recordCount = 0;
72 uint64_t PerfEventsTest::g_statCount = 0;
73 
RecordCount(std::unique_ptr<PerfEventRecord> record)74 bool PerfEventsTest::RecordCount(std::unique_ptr<PerfEventRecord> record)
75 {
76     g_recordCount++;
77     return true;
78 }
79 
StatCount(const std::map<std::string,std::unique_ptr<PerfEvents::CountEvent>> & countEvents)80 void PerfEventsTest::StatCount(
81     const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents)
82 {
83     g_statCount++;
84 }
85 
TestCodeThread()86 void PerfEventsTest::TestCodeThread()
87 {
88     std::vector<std::unique_ptr<char[]>> mems;
89     int tid = gettid();
90     printf("%s:%d ++\n", __FUNCTION__, tid);
91     for (int n = 0; n < TRIPLE; n++) {
92         std::this_thread::sleep_for(TEST_CODE_SLEEP_BEFORE_RUN);
93         constexpr size_t memSize {TEST_CODE_MEM_FILE_SIZE};
94         for (int i = 0; i < TEST_CODE_RUN_TIME; i++) {
95             if (i % DOUBLE == 0) {
96                 mems.push_back(std::make_unique<char[]>(memSize));
97             } else {
98                 mems.push_back(std::make_unique<char[]>(memSize * DOUBLE));
99             }
100         }
101 
102         for (int i = 0; i < TEST_CODE_RUN_TIME; i++) {
103             mems.pop_back();
104         }
105 
106         std::this_thread::sleep_for(TEST_CODE_SLEEP_AFTER_RUN);
107     }
108     printf("%s:%d --\n", __FUNCTION__, tid);
109 }
110 
RunTestThreads(std::vector<std::thread> & threads)111 void PerfEventsTest::RunTestThreads(std::vector<std::thread> &threads)
112 {
113     long processorNum = GetProcessorNum();
114     for (long i = 0; i < processorNum; i++) {
115         threads.emplace_back(std::thread(&TestCodeThread));
116     }
117 }
118 
119 // it isn't include sample and stat
SetAllConfig(PerfEvents & event)120 void PerfEventsTest::SetAllConfig(PerfEvents &event)
121 {
122     std::vector<pid_t> selectCpus_;
123     event.SetCpu(selectCpus_);
124     std::vector<pid_t> pids;
125     event.SetPid(pids);
126     event.SetSystemTarget(true);
127     event.SetTimeOut(DEFAULT_TRACKING_TIME);
128     event.SetInherit(false);
129     std::vector<std::string> trackedCommand_ {};
130     event.SetTrackedCommand(trackedCommand_);
131     const unsigned int frequency = 4000;
132     event.SetSampleFrequency(frequency);
133     const uint32_t dwarfSampleStackSize = 64;
134     event.SetDwarfSampleStackSize(dwarfSampleStackSize);
135     const int clockId = 1;
136     event.SetClockId(clockId);
137 
138     // addevent must be tail
139     event.AddDefaultEvent(PERF_TYPE_HARDWARE);
140     event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
141 }
142 
RunTrack(PerfEvents & event)143 static void RunTrack(PerfEvents &event)
144 {
145     ASSERT_EQ(event.StartTracking(), true);
146 }
147 
148 /**
149  * @tc.name: Test
150  * @tc.desc:
151  * @tc.type: FUNC
152  */
153 HWTEST_F(PerfEventsTest, GetSupportEvents, TestSize.Level1)
154 {
155     ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
156     StdoutRecord stdoutRecord;
157     stdoutRecord.Start();
158 
159     PerfEvents event;
160     perf_type_id id = PERF_TYPE_HARDWARE;
161     while (id < PERF_TYPE_MAX) {
162         std::map<__u64, std::string> supportEvent = event.GetSupportEvents(id);
163         for (auto it = supportEvent.begin(); it != supportEvent.end(); ++it) {
164             printf("[%lld]\t%s\n", it->first, it->second.c_str());
165         }
166         id = perf_type_id(id + 1);
167     }
168 
169     std::string stringOut = stdoutRecord.Stop();
170 }
171 
172 HWTEST_F(PerfEventsTest, GetTypeName, TestSize.Level1)
173 {
174     ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
175     StdoutRecord stdoutRecord;
176     stdoutRecord.Start();
177 
178     PerfEvents event;
179     perf_type_id id = PERF_TYPE_HARDWARE;
180     while (id < PERF_TYPE_MAX) {
181         std::string typeName = event.GetTypeName(id);
182         EXPECT_GT(typeName.size(), 0u) << "the type should have name";
183         printf("type[%d]\tname : %s\n", id, typeName.c_str());
184         id = perf_type_id(id + 1);
185     }
186 
187     std::string stringOut = stdoutRecord.Stop();
188 }
189 
190 HWTEST_F(PerfEventsTest, RecordNormal, TestSize.Level1)
191 {
192     ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
193     StdoutRecord stdoutRecord;
194     stdoutRecord.Start();
195 
196     PerfEvents event;
197     // prepare
198     g_recordCount = 0;
199     event.SetMmapPages(DEFAULT_SAMPLE_MMAPAGE);
200     event.SetRecordCallBack(RecordCount);
201 
202     std::vector<pid_t> selectCpus_;
203     event.SetCpu(selectCpus_);
204     std::vector<pid_t> pids;
205     event.SetPid(pids);
206     event.SetSystemTarget(true);
207     event.SetTimeOut(DEFAULT_TRACKING_TIME);
208     event.SetInherit(false);
209     std::vector<std::string> trackedCommand_ {};
210     event.SetTrackedCommand(trackedCommand_);
211     event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
212     event.AddDefaultEvent(PERF_TYPE_HARDWARE);
213 
214     ASSERT_EQ(event.PrepareTracking(), true);
215     std::thread runThread(RunTrack, std::ref(event));
216     std::vector<std::thread> testThreads;
217     RunTestThreads(testThreads);
218 
219     std::this_thread::sleep_for(TEST_TIME);
220     EXPECT_EQ(event.PauseTracking(), true);
221     std::this_thread::sleep_for(TEST_TIME); // wait for clearing mmap buffer
222     uint64_t recordCount = g_recordCount;
223     std::this_thread::sleep_for(TEST_TIME);
224     EXPECT_EQ(recordCount, g_recordCount) << "now should have no record";
225     EXPECT_EQ(event.ResumeTracking(), true);
226     TestCodeThread();
227     std::this_thread::sleep_for(TEST_TIME);
228     EXPECT_EQ(event.StopTracking(), true);
229     runThread.join();
230     for (std::thread &t : testThreads) {
231         t.join();
232     }
233     ASSERT_GT(g_recordCount, recordCount) << "should have more records";
234 
235     size_t lostSamples = 0;
236     size_t lostNonSamples = 0;
237     event.GetLostSamples(lostSamples, lostNonSamples);
238 
239     std::string stringOut = stdoutRecord.Stop();
240 }
241 
242 HWTEST_F(PerfEventsTest, RecordSetAll, TestSize.Level1)
243 {
244     ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
245     StdoutRecord stdoutRecord;
246     stdoutRecord.Start();
247 
248     PerfEvents event;
249     // prepare
250     g_recordCount = 0;
251     event.SetMmapPages(DEFAULT_SAMPLE_MMAPAGE);
252     event.SetRecordCallBack(RecordCount);
253     SetAllConfig(event);
254     ASSERT_EQ(event.PrepareTracking(), true);
255     std::thread runThread(RunTrack, std::ref(event));
256     std::vector<std::thread> testThreads;
257     RunTestThreads(testThreads);
258 
259     std::this_thread::sleep_for(TEST_TIME);
260     EXPECT_EQ(event.PauseTracking(), true);
261     std::this_thread::sleep_for(TEST_TIME); // wait for clearing mmap buffer
262     uint64_t recordCount = g_recordCount;
263     std::this_thread::sleep_for(TEST_TIME);
264     EXPECT_EQ(recordCount, g_recordCount) << "now should have no record";
265     EXPECT_EQ(event.ResumeTracking(), true);
266     TestCodeThread();
267     std::this_thread::sleep_for(TEST_TIME);
268     EXPECT_EQ(event.StopTracking(), true);
269     runThread.join();
270     for (std::thread &t : testThreads) {
271         t.join();
272     }
273     ASSERT_GT(g_recordCount, recordCount) << "should have more records";
274 
275     std::string stringOut = stdoutRecord.Stop();
276 }
277 
278 HWTEST_F(PerfEventsTest, StatNormal, TestSize.Level1)
279 {
280     ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
281     StdoutRecord stdoutRecord;
282     stdoutRecord.Start();
283 
284     PerfEvents event;
285     // prepare
286     g_statCount = 0;
287     std::vector<pid_t> selectCpus_;
288     event.SetCpu(selectCpus_);
289     std::vector<pid_t> pids;
290     event.SetPid(pids);
291     event.SetSystemTarget(true);
292     event.SetTimeOut(DEFAULT_TRACKING_TIME);
293     event.SetTimeReport(DEFAULT_STAT_REPORT_TIME);
294     event.SetVerboseReport(false);
295     event.SetInherit(false);
296     std::vector<std::string> trackedCommand_;
297     event.SetTrackedCommand(trackedCommand_);
298     event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
299     event.AddDefaultEvent(PERF_TYPE_TRACEPOINT);
300     event.SetStatCallBack(StatCount);
301     ASSERT_EQ(event.PrepareTracking(), true);
302     std::thread runThread(RunTrack, std::ref(event));
303     std::vector<std::thread> testThreads;
304     RunTestThreads(testThreads);
305 
306     std::this_thread::sleep_for(TEST_TIME);
307     EXPECT_EQ(event.PauseTracking(), true);
308     EXPECT_GT(g_statCount, 0u) << "should have stats";
309     uint64_t statCount = g_statCount;
310     std::this_thread::sleep_for(TEST_TIME);
311     EXPECT_EQ(event.ResumeTracking(), true);
312     std::this_thread::sleep_for(TEST_TIME);
313     EXPECT_EQ(event.StopTracking(), true);
314     runThread.join();
315     for (std::thread &t : testThreads) {
316         t.join();
317     }
318     EXPECT_GT(g_statCount, statCount) << "should have more stats";
319 
320     std::string stringOut = stdoutRecord.Stop();
321 }
322 } // namespace HiPerf
323 } // namespace Developtools
324 } // namespace OHOS
325