• 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 <cstdio>
17 #include <cstring>
18 #include <unistd.h>
19 #include <cstdlib>
20 #include <pthread.h>
21 #include <vector>
22 #include <ctime>
23 #include <csignal>
24 #include <atomic>
25 #include <memory>
26 
27 namespace {
28 struct PerfData {
29     long long malloc_total_time;
30     long long free_total_time;
31     long long times;
32 };
33 
34 static int duration;
35 static int mem_size;
36 static std::vector<PerfData> thread_data;
37 static std::atomic<long long> times;
38 static std::atomic<long long> malloc_total_time;
39 static std::atomic<long long> free_total_time;
40 static constexpr int nInstallMallocHookSignal = 36;
41 static constexpr int g_duration = 30 * 60;
42 static constexpr int g_memSize = 19;
43 
user_thread(void * param)44 void* user_thread(void* param)
45 {
46     int idx = *static_cast<int*>(param);
47     struct timespec begin_time;
48     struct timespec end_time;
49     struct timespec begin_time_malloc;
50     struct timespec end_time_malloc;
51     struct timespec begin_time_free;
52     struct timespec end_time_free;
53 
54     clock_gettime(CLOCK_REALTIME, &begin_time);
55     int display_size = mem_size > 5? 5 : mem_size;
56     do {
57         clock_gettime(CLOCK_REALTIME, &end_time);
58         if (end_time.tv_sec - begin_time.tv_sec >= duration) {
59             break;
60         }
61         clock_gettime(CLOCK_REALTIME, &begin_time_malloc);
62         char* mem = (char *)malloc(mem_size);
63         clock_gettime(CLOCK_REALTIME, &end_time_malloc);
64         std::atomic_fetch_add_explicit(
65             &malloc_total_time,
66             static_cast<long long>((end_time_malloc.tv_sec - begin_time_malloc.tv_sec) * 1000000000L +
67                                    (end_time_malloc.tv_nsec - begin_time_malloc.tv_nsec)),
68             std::memory_order_relaxed);
69         long long current_times = ++times;
70         long long timeBase = 10000;
71         if (current_times % timeBase == 0) {
72             printf("Thread %d, %lld: ", idx + 1, current_times);
73             for (int i = 0 ; i < display_size ; i++) {
74                 printf("%d ", mem[i]);
75             }
76             printf("\n");
77         }
78         clock_gettime(CLOCK_REALTIME, &begin_time_free);
79         free(mem);
80         clock_gettime(CLOCK_REALTIME, &end_time_free);
81         std::atomic_fetch_add_explicit(
82             &free_total_time,
83             static_cast<long long>((end_time_free.tv_sec - begin_time_free.tv_sec) * 1000000000L +
84                                    (end_time_free.tv_nsec - begin_time_free.tv_nsec)),
85             std::memory_order_relaxed);
86     }
87     while (1);
88     return nullptr;
89 }
90 #define PRINTF_DATA(fileptr, fmt, ...) \
91 {                              \
92     do { \
93         fprintf(stderr, fmt, ## __VA_ARGS__); \
94         fprintf(fileptr, fmt, ## __VA_ARGS__); \
95         fflush(fileptr); \
96     } while (0); \
97 }
98 
usage()99 void usage()
100 {
101     printf("Usage: perf_test_data <-o output_file_name> [-t thread_num[] [-d duration] [-s mem_size]\n");
102 }
103 
FileClose(FILE * fp)104 void FileClose(FILE* fp)
105 {
106     if (fp != nullptr) {
107         fclose(fp);
108     }
109 }
110 
111 } // namespace
112 
main(int argc,char * argv[])113 int main(int argc, char *argv[])
114 {
115     int thread_num = 1;
116     duration = g_duration;
117     mem_size = g_memSize;
118     std::unique_ptr<FILE, void (*)(FILE*)> out_fp(nullptr, nullptr);
119     for (int idx = 1; idx < argc; ++idx) {
120         if (strcmp(argv[idx], "-o") == 0) {
121             if (idx + 1 >= argc) {
122                 usage();
123                 return 1;
124             } else {
125                 ++idx;
126                 out_fp = std::unique_ptr<FILE, void (*)(FILE*)>(fopen(argv[idx], "w"), FileClose);
127                 if (out_fp == nullptr) {
128                     printf("File '%s' can't be opened.\n", argv[idx]);
129                     return 1;
130                 }
131             }
132         } else if (strcmp(argv[idx], "-t") == 0) {
133             if (idx + 1 >= argc) {
134                 usage();
135                 return 1;
136             } else {
137                 ++idx;
138                 thread_num = atoi(argv[idx]);
139                 if (thread_num <= 0) {
140                     printf("Thread number can't be less or equal zero.\n");
141                     return 1;
142                 }
143             }
144         } else if (strcmp(argv[idx], "-d") == 0) {
145             if (idx + 1 >= argc) {
146                 usage();
147                 return 1;
148             } else {
149                 ++idx;
150                 duration = atoi(argv[idx]);
151                 if (duration <= 0) {
152                     printf("duration can't be less or equal zero.\n");
153                     return 1;
154                 }
155             }
156         } else if (strcmp(argv[idx], "-s") == 0) {
157             if (idx + 1 >= argc) {
158                 usage();
159                 return 1;
160             } else {
161                 ++idx;
162                 mem_size = atoi(argv[idx]);
163                 if (mem_size <= 0) {
164                     printf("memory size can't be less or equal zero.\n");
165                     return 1;
166                 }
167             }
168         }
169     }
170     if (out_fp == nullptr) {
171         usage();
172         return 1;
173     }
174 
175     thread_data.resize(thread_num);
176     pthread_t* thr_array = (pthread_t*)malloc(sizeof(pthread_t) * thread_num);
177     int idxSituation;
178     int idxSituationMax = 2;
179     int pid = static_cast<int>(getpid());
180     PRINTF_DATA(out_fp.get(), "PID: %d, file: %d.nativehook\n", pid, pid);
181     PRINTF_DATA(out_fp.get(), "Thread number: %d, duration: %d seconds, memory size: %d bytes\n", thread_num, duration,
182                 mem_size);
183     for (idxSituation = 0; idxSituation < idxSituationMax; ++idxSituation) {
184         if (idxSituation == 0) {
185             PRINTF_DATA(out_fp.get(), "No hook situation\n");
186         } else {
187             PRINTF_DATA(out_fp.get(), "\nWith hook situation\n");
188             raise(nInstallMallocHookSignal);
189         }
190         int idx;
191 
192         std::atomic_store_explicit(&times, static_cast<long long>(0), std::memory_order_seq_cst);
193         std::atomic_store_explicit(&malloc_total_time, static_cast<long long>(0), std::memory_order_seq_cst);
194         std::atomic_store_explicit(&free_total_time, static_cast<long long>(0), std::memory_order_seq_cst);
195 
196         for (idx = 0; idx < thread_num; ++idx) {
197             if (pthread_create(thr_array + idx, nullptr, user_thread, reinterpret_cast<void*>(&idx)) != 0) {
198                 printf("Creating thread failed.\n");
199             }
200         }
201 
202         for (idx = 0; idx < thread_num; ++idx) {
203             pthread_join(thr_array[idx], nullptr);
204         }
205         long long total_times = times.load(std::memory_order_relaxed);
206         PRINTF_DATA(out_fp.get(), "The total times(malloc/free): %lld\n", total_times);
207     }
208     free(thr_array);
209     printf("Exit\n");
210 }
211