1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 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 27namespace { 28static int g_duration; 29static int g_memSize; 30static std::atomic<long long> g_times; 31static std::atomic<long long> g_mallocTotalTime; 32static std::atomic<long long> g_freeTotalTime; 33static constexpr int N_INSTALL_MALLOC_HOOK_SIGNAL = 36; 34static constexpr int DURATION_TIME = 30 * 60; 35static constexpr int MEMORY_BUFFER_SIZE = 19; 36 37void* UserThread(void* param) 38{ 39 int idx = *static_cast<int*>(param); 40 struct timespec beginTime; 41 struct timespec endTime; 42 struct timespec beginTimeMalloc; 43 struct timespec endTimeMalloc; 44 struct timespec beginTimeFree; 45 struct timespec endTimeFree; 46 47 clock_gettime(CLOCK_REALTIME, &beginTime); 48 int displaySize = g_memSize > 5 ? 5 : g_memSize; 49 do { 50 clock_gettime(CLOCK_REALTIME, &endTime); 51 if (endTime.tv_sec - beginTime.tv_sec >= g_duration) { 52 break; 53 } 54 clock_gettime(CLOCK_REALTIME, &beginTimeMalloc); 55 char* mem = static_cast<char *>(malloc(g_memSize)); 56 if (mem == nullptr) { 57 printf("Error: malloc mem memory failed.\n"); 58 return nullptr; 59 } 60 clock_gettime(CLOCK_REALTIME, &endTimeMalloc); 61 std::atomic_fetch_add_explicit( 62 &g_mallocTotalTime, 63 static_cast<long long>((endTimeMalloc.tv_sec - beginTimeMalloc.tv_sec) * 1000000000L + 64 (endTimeMalloc.tv_nsec - beginTimeMalloc.tv_nsec)), 65 std::memory_order_relaxed); 66 long long currentTimes = ++g_times; 67 long long timeBase = 10000; 68 if (currentTimes % timeBase == 0) { 69 printf("Thread %d, %lld: ", idx + 1, currentTimes); 70 for (int i = 0 ; i < displaySize ; i++) { 71 printf("%d ", mem[i]); 72 } 73 printf("\n"); 74 } 75 clock_gettime(CLOCK_REALTIME, &beginTimeFree); 76 if (mem != nullptr) { 77 free(mem); 78 } 79 clock_gettime(CLOCK_REALTIME, &endTimeFree); 80 std::atomic_fetch_add_explicit( 81 &g_freeTotalTime, 82 static_cast<long long>((endTimeFree.tv_sec - beginTimeFree.tv_sec) * 1000000000L + 83 (endTimeFree.tv_nsec - beginTimeFree.tv_nsec)), 84 std::memory_order_relaxed); 85 } 86 while (true); 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 98void Usage() 99{ 100 printf("Usage: perf_test_data <-o output_file_name> [-t threadNum[] [-d g_duration] [-s g_memSize]\n"); 101} 102 103void FileClose(FILE* fp) 104{ 105 if (fp != nullptr) { 106 fclose(fp); 107 } 108} 109 110} // namespace 111 112int main(int argc, char *argv[]) 113{ 114 int threadNum = 1; 115 g_duration = DURATION_TIME; 116 g_memSize = MEMORY_BUFFER_SIZE; 117 std::unique_ptr<FILE, void (*)(FILE*)> outFp(nullptr, nullptr); 118 for (int idx = 1; idx < argc; ++idx) { 119 if (strcmp(argv[idx], "-o") == 0) { 120 if (idx + 1 >= argc) { 121 Usage(); 122 return 1; 123 } else { 124 ++idx; 125 outFp = std::unique_ptr<FILE, void (*)(FILE*)>(fopen(argv[idx], "w"), FileClose); 126 if (outFp == nullptr) { 127 printf("File '%s' can't be opened.\n", argv[idx]); 128 return 1; 129 } 130 } 131 } else if (strcmp(argv[idx], "-t") == 0) { 132 if (idx + 1 >= argc) { 133 Usage(); 134 return 1; 135 } else { 136 ++idx; 137 threadNum = atoi(argv[idx]); 138 if (threadNum <= 0) { 139 printf("Thread number can't be less or equal zero.\n"); 140 return 1; 141 } 142 } 143 } else if (strcmp(argv[idx], "-d") == 0) { 144 if (idx + 1 >= argc) { 145 Usage(); 146 return 1; 147 } else { 148 ++idx; 149 g_duration = atoi(argv[idx]); 150 if (g_duration <= 0) { 151 printf("g_duration can't be less or equal zero.\n"); 152 return 1; 153 } 154 } 155 } else if (strcmp(argv[idx], "-s") == 0) { 156 if (idx + 1 >= argc) { 157 Usage(); 158 return 1; 159 } else { 160 ++idx; 161 g_memSize = atoi(argv[idx]); 162 if (g_memSize <= 0) { 163 printf("memory size can't be less or equal zero.\n"); 164 return 1; 165 } 166 } 167 } 168 } 169 if (outFp == nullptr) { 170 Usage(); 171 return 1; 172 } 173 pthread_t* thrArray = static_cast<pthread_t*>(malloc(sizeof(pthread_t) * threadNum)); 174 if (thrArray == nullptr) { 175 printf("malloc thrArray memory failed.\n"); 176 return 1; 177 } 178 int idxSituation; 179 int idxSituationMax = 2; 180 int pid = static_cast<int>(getpid()); 181 PRINTF_DATA(outFp.get(), "PID: %d, file: %d.nativehook\n", pid, pid); 182 PRINTF_DATA(outFp.get(), 183 "Thread number: %d, duration: %d seconds, memory size: %d bytes\n", 184 threadNum, 185 g_duration, 186 g_memSize); 187 for (idxSituation = 0; idxSituation < idxSituationMax; ++idxSituation) { 188 if (idxSituation == 0) { 189 PRINTF_DATA(outFp.get(), "No hook situation\n"); 190 } else { 191 PRINTF_DATA(outFp.get(), "\nWith hook situation\n"); 192 raise(N_INSTALL_MALLOC_HOOK_SIGNAL); 193 } 194 int idx; 195 196 std::atomic_store_explicit(&g_times, static_cast<long long>(0), std::memory_order_seq_cst); 197 std::atomic_store_explicit(&g_mallocTotalTime, static_cast<long long>(0), std::memory_order_seq_cst); 198 std::atomic_store_explicit(&g_freeTotalTime, static_cast<long long>(0), std::memory_order_seq_cst); 199 200 for (idx = 0; idx < threadNum; ++idx) { 201 if (pthread_create(thrArray + idx, nullptr, UserThread, reinterpret_cast<void*>(&idx)) != 0) { 202 printf("Creating thread failed.\n"); 203 } 204 } 205 206 for (idx = 0; idx < threadNum; ++idx) { 207 pthread_join(thrArray[idx], nullptr); 208 } 209 long long totalTimes = g_times.load(std::memory_order_relaxed); 210 PRINTF_DATA(outFp.get(), "The total g_times(malloc/free): %lld\n", totalTimes); 211 } 212 if (thrArray != nullptr) { 213 free(thrArray); 214 } 215 printf("Exit\n"); 216} 217