1/* 2 * Copyright (c) 2023 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 <benchmark/benchmark.h> 17 18#include <securec.h> 19#include <string> 20#include <vector> 21#include <unistd.h> 22#include "dfx_define.h" 23#include "dfx_log.h" 24#include <libunwind.h> 25#include "dfx_test_util.h" 26 27using namespace OHOS::HiviewDFX; 28using namespace std; 29 30static constexpr size_t TEST_MIN_UNWIND_FRAMES = 5; 31 32NOINLINE static size_t TestFunc5(size_t (*func)(void)) 33{ 34 return func(); 35} 36 37NOINLINE static size_t TestFunc4(size_t (*func)(void)) 38{ 39 return TestFunc5(func); 40} 41 42NOINLINE static size_t TestFunc3(size_t (*func)(void)) 43{ 44 return TestFunc4(func); 45} 46 47NOINLINE static size_t TestFunc2(size_t (*func)(void)) 48{ 49 return TestFunc3(func); 50} 51 52NOINLINE static size_t TestFunc1(size_t (*func)(void)) 53{ 54 return TestFunc2(func); 55} 56 57static size_t UnwindLocal() 58{ 59 unw_context_t context; 60 (void)memset_s(&context, sizeof(unw_context_t), 0, sizeof(unw_context_t)); 61 unw_getcontext(&context); 62 63 unw_cursor_t cursor; 64 unw_init_local(&cursor, &context); 65 66 std::vector<unw_word_t> pcs; 67 size_t index = 0; 68 unw_word_t pc = 0; 69 unw_word_t prevPc = 0; 70 do { 71 if ((unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t*)(&(pc)))) || (prevPc == pc)) { 72 break; 73 } 74 pcs.emplace_back(pc); 75 prevPc = pc; 76 index++; 77 } while (unw_step(&cursor) > 0); 78 DFXLOGU("%{public}s pcs.size: %{public}zu", __func__, pcs.size()); 79 return pcs.size(); 80} 81 82static void Run(benchmark::State& state, size_t (*func)(void)) 83{ 84 DFXLOGU("++++++pid: %{public}d", getpid()); 85 for (const auto& _ : state) { 86 if (TestFunc1(func) < TEST_MIN_UNWIND_FRAMES) { 87 state.SkipWithError("Failed to unwind."); 88 } 89 } 90 DFXLOGU("------pid: %{public}d", getpid()); 91} 92 93/** 94* @tc.name: BenchmarkUnwindLocal 95* @tc.desc: Unwind local 96* @tc.type: FUNC 97*/ 98static void BenchmarkUnwindLocal(benchmark::State& state) 99{ 100 Run(state, UnwindLocal); 101} 102BENCHMARK(BenchmarkUnwindLocal); 103 104/** 105* @tc.name: BenchmarkUnwindLocalCache 106* @tc.desc: Unwind local cache 107* @tc.type: FUNC 108*/ 109static void BenchmarkUnwindLocalCache(benchmark::State& state) 110{ 111 Run(state, UnwindLocal); 112} 113BENCHMARK(BenchmarkUnwindLocalCache); 114