• 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 #include <chrono>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <new>
19 #include <pthread.h>
20 #include <sys/syscall.h>
21 #include <unistd.h>
22 
23 #pragma clang optimize off
24 
25 
26 namespace {
27 constexpr int MALLOC_SIZE = 1000;
28 constexpr int TIME_BASE = 1000;
29 constexpr int DATA_SIZE = 200;
30 constexpr int SLEEP_TIME = 200;
31 constexpr int ARGC_NUM_MAX = 4;
32 constexpr int ARGC_NUM_MUST = 3;
33 constexpr int ARGC_MALLOC_TIMES = 2;
34 constexpr int ARGC_STICK_DEPTH = 3;
35 unsigned int g_stickDepth = 100;
36 
37 using StaticSpace = struct {
38     int data[DATA_SIZE];
39 };
40 
41 class Timer {
42 public:
43     using Clock = std::chrono::steady_clock;
44     using TimePoint = Clock::time_point;
45 
Timer()46     Timer() : startTime_(Now()) {}
47 
~Timer()48     ~Timer() {}
49 
ElapsedUs()50     long ElapsedUs()
51     {
52         auto currentTime = Now();
53         return std::chrono::duration_cast<std::chrono::microseconds>(currentTime - startTime_).count();
54     }
55 
Reset()56     void Reset()
57     {
58         startTime_ = Now();
59     }
60 
61 protected:
Now()62     TimePoint Now()
63     {
64         return Clock::now();
65     }
66 
67 private:
68     TimePoint startTime_;
69 };
70 
DepthMalloc(int depth,int mallocSize)71 char *DepthMalloc(int depth, int mallocSize)
72 {
73     if (mallocSize <= 0) {
74         return nullptr;
75     }
76     StaticSpace staticeData;
77     if (depth == 0) {
78         staticeData.data[0] = 1;
79         return new char[mallocSize];
80     }
81     return (DepthMalloc(depth - 1, mallocSize));
82 }
83 
DepthFree(int depth,char * p)84 void DepthFree(int depth, char *p)
85 {
86     StaticSpace staticeData;
87     if (depth == 0) {
88         staticeData.data[0] = 1;
89         delete []p;
90         return;
91     }
92     return (DepthFree(depth - 1, p));
93 }
94 
thread_func_cpp(void * param)95 void* thread_func_cpp(void* param)
96 {
97     char *p = nullptr;
98     long tid = syscall(SYS_gettid);
99     printf("start thread %ld\n", tid);
100     int times = *static_cast<int*>(param);
101     int idx = 0;
102     while (idx < times) {
103         p = DepthMalloc(g_stickDepth, MALLOC_SIZE);
104         if (idx % TIME_BASE == 0) {
105             printf("thread %ld malloc %d times\n", tid, idx);
106         }
107         if (p) {
108             DepthFree(g_stickDepth, p);
109         }
110         idx++;
111     }
112     return nullptr;
113 }
114 
ThreadTimeCost(int threadNum,int mallocTimes)115 int ThreadTimeCost(int threadNum, int mallocTimes) {
116     Timer timer = {};
117     if (threadNum <= 0) {
118         printf("threadNum less than or equal to 0.\n");
119         return 1;
120     }
121     pthread_t* thr_array = new (std::nothrow) pthread_t[threadNum];
122     if (!thr_array) {
123         printf("new thread array failed.\n");
124         return 1;
125     }
126     int idx;
127     for (idx = 0; idx < threadNum; ++idx) {
128         if (pthread_create(thr_array + idx, nullptr, thread_func_cpp, static_cast<void*>(&mallocTimes)) != 0) {
129             printf("Creating thread failed.\n");
130         }
131     }
132     for (idx = 0; idx < threadNum; ++idx) {
133         pthread_join(thr_array[idx], nullptr);
134     }
135     delete []thr_array;
136     auto timeCost = timer.ElapsedUs();
137     printf("Before hook, time cost %ldus.\nAfter hook test sleeping 200 ......., please send signal\n", timeCost);
138     sleep(SLEEP_TIME);
139     printf("Hook test start\n");
140     Timer hooktimer = {};
141     pthread_t* thr_array_hook = new (std::nothrow) pthread_t[threadNum];
142     if (!thr_array_hook) {
143         printf("new thread lock array failed.\n");
144         return 1;
145     }
146     for (idx = 0; idx < threadNum; ++idx) {
147         if (pthread_create(thr_array_hook + idx, nullptr, thread_func_cpp, static_cast<void*>(&mallocTimes)) !=
148             0) {
149             printf("Creating thread failed.\n");
150         }
151     }
152     for (idx = 0; idx < threadNum; ++idx) {
153         pthread_join(thr_array_hook[idx], nullptr);
154     }
155     delete []thr_array_hook;
156     auto hookCost = hooktimer.ElapsedUs();
157     printf("After hook, time cost %ldus.\nPerformance test finish!", hookCost);
158     return 0;
159 }
160 } // namespace
161 
main(int argc,char * argv[])162 int main(int argc, char *argv[])
163 {
164     int threadNum = 1;
165     int mallocTimes = 0;
166     if  (argc >= ARGC_NUM_MUST) {
167         if (atoi(argv[1]) > 0) {
168             threadNum = atoi(argv[1]);
169         }
170         mallocTimes = atoi(argv[ARGC_MALLOC_TIMES]);
171         if (argc == ARGC_NUM_MAX) {
172             g_stickDepth = atoi(argv[ARGC_STICK_DEPTH]);
173         }
174     } else {
175         printf("command error\n");
176         return 0;
177     }
178     printf("Test start %d thread, malloc %d times\n", threadNum, mallocTimes);
179     if (!ThreadTimeCost(threadNum, mallocTimes)) {
180         printf("Test success end!\n");
181     } else {
182         printf("Test failure end!\n");
183     }
184 }
185 
186 #pragma clang optimize on
187