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