1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include <benchmark/benchmark.h> 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <memory> 19800b99b8Sopenharmony_ci#include <securec.h> 20800b99b8Sopenharmony_ci#include <string> 21800b99b8Sopenharmony_ci#include <vector> 22800b99b8Sopenharmony_ci#include <unistd.h> 23800b99b8Sopenharmony_ci#include <unwindstack/Elf.h> 24800b99b8Sopenharmony_ci#include <unwindstack/Maps.h> 25800b99b8Sopenharmony_ci#include <unwindstack/Memory.h> 26800b99b8Sopenharmony_ci#include <unwindstack/Regs.h> 27800b99b8Sopenharmony_ci#include <unwindstack/RegsGetLocal.h> 28800b99b8Sopenharmony_ci#include <unwindstack/Unwinder.h> 29800b99b8Sopenharmony_ci#include "dfx_define.h" 30800b99b8Sopenharmony_ci#include "dfx_log.h" 31800b99b8Sopenharmony_ci 32800b99b8Sopenharmony_ciusing namespace OHOS::HiviewDFX; 33800b99b8Sopenharmony_ciusing namespace std; 34800b99b8Sopenharmony_ci 35800b99b8Sopenharmony_cistatic constexpr size_t TEST_MIN_UNWIND_FRAMES = 5; 36800b99b8Sopenharmony_cistatic constexpr size_t MAX_FRAMES = 32; 37800b99b8Sopenharmony_ci 38800b99b8Sopenharmony_cistruct UnwindData { 39800b99b8Sopenharmony_ci std::shared_ptr<unwindstack::Memory>& processMemory; 40800b99b8Sopenharmony_ci unwindstack::Maps* maps; 41800b99b8Sopenharmony_ci bool isFillFrames = false; 42800b99b8Sopenharmony_ci}; 43800b99b8Sopenharmony_ci 44800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc5(size_t (*func)(void*), void* data) 45800b99b8Sopenharmony_ci{ 46800b99b8Sopenharmony_ci return func(data); 47800b99b8Sopenharmony_ci} 48800b99b8Sopenharmony_ci 49800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc4(size_t (*func)(void*), void* data) 50800b99b8Sopenharmony_ci{ 51800b99b8Sopenharmony_ci return TestFunc5(func, data); 52800b99b8Sopenharmony_ci} 53800b99b8Sopenharmony_ci 54800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc3(size_t (*func)(void*), void* data) 55800b99b8Sopenharmony_ci{ 56800b99b8Sopenharmony_ci return TestFunc4(func, data); 57800b99b8Sopenharmony_ci} 58800b99b8Sopenharmony_ci 59800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc2(size_t (*func)(void*), void* data) 60800b99b8Sopenharmony_ci{ 61800b99b8Sopenharmony_ci return TestFunc3(func, data); 62800b99b8Sopenharmony_ci} 63800b99b8Sopenharmony_ci 64800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc1(size_t (*func)(void*), void* data) 65800b99b8Sopenharmony_ci{ 66800b99b8Sopenharmony_ci return TestFunc2(func, data); 67800b99b8Sopenharmony_ci} 68800b99b8Sopenharmony_ci 69800b99b8Sopenharmony_cistatic size_t UnwindLocal(MAYBE_UNUSED void* data) 70800b99b8Sopenharmony_ci{ 71800b99b8Sopenharmony_ci UnwindData* dataPtr = reinterpret_cast<UnwindData*>(data); 72800b99b8Sopenharmony_ci if (dataPtr == nullptr) { 73800b99b8Sopenharmony_ci return 0; 74800b99b8Sopenharmony_ci } 75800b99b8Sopenharmony_ci std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal()); 76800b99b8Sopenharmony_ci unwindstack::RegsGetLocal(regs.get()); 77800b99b8Sopenharmony_ci unwindstack::Unwinder unwinder(MAX_FRAMES, dataPtr->maps, regs.get(), dataPtr->processMemory); 78800b99b8Sopenharmony_ci unwinder.SetResolveNames(dataPtr->isFillFrames); 79800b99b8Sopenharmony_ci unwinder.Unwind(); 80800b99b8Sopenharmony_ci auto unwSize = unwinder.NumFrames(); 81800b99b8Sopenharmony_ci DFXLOGU("%{public}s frames.size: %{public}zu", __func__, unwSize); 82800b99b8Sopenharmony_ci if (dataPtr->isFillFrames) { 83800b99b8Sopenharmony_ci for (size_t i = 0; i < unwSize; ++i) { 84800b99b8Sopenharmony_ci auto str = unwinder.FormatFrame(i); 85800b99b8Sopenharmony_ci DFXLOGU("%{public}s frames: %{public}s", __func__, str.c_str()); 86800b99b8Sopenharmony_ci } 87800b99b8Sopenharmony_ci } 88800b99b8Sopenharmony_ci return unwSize; 89800b99b8Sopenharmony_ci} 90800b99b8Sopenharmony_ci 91800b99b8Sopenharmony_cistatic void Run(benchmark::State& state, size_t (*func)(void*), void* data) 92800b99b8Sopenharmony_ci{ 93800b99b8Sopenharmony_ci DFXLOGU("++++++pid: %{public}d", getpid()); 94800b99b8Sopenharmony_ci for (const auto& _ : state) { 95800b99b8Sopenharmony_ci if (TestFunc1(func, data) < TEST_MIN_UNWIND_FRAMES) { 96800b99b8Sopenharmony_ci state.SkipWithError("Failed to unwind."); 97800b99b8Sopenharmony_ci } 98800b99b8Sopenharmony_ci } 99800b99b8Sopenharmony_ci DFXLOGU("------pid: %{public}d", getpid()); 100800b99b8Sopenharmony_ci} 101800b99b8Sopenharmony_ci 102800b99b8Sopenharmony_ci/** 103800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindStackLocal 104800b99b8Sopenharmony_ci* @tc.desc: UnwindStack local 105800b99b8Sopenharmony_ci* @tc.type: FUNC 106800b99b8Sopenharmony_ci*/ 107800b99b8Sopenharmony_cistatic void BenchmarkUnwindStackLocal(benchmark::State& state) 108800b99b8Sopenharmony_ci{ 109800b99b8Sopenharmony_ci auto processMemory = unwindstack::Memory::CreateProcessMemory(getpid()); 110800b99b8Sopenharmony_ci unwindstack::LocalMaps maps; 111800b99b8Sopenharmony_ci if (!maps.Parse()) { 112800b99b8Sopenharmony_ci state.SkipWithError("Failed to parse local maps."); 113800b99b8Sopenharmony_ci } 114800b99b8Sopenharmony_ci 115800b99b8Sopenharmony_ci UnwindData data = {.processMemory = processMemory, .maps = &maps, .isFillFrames = false}; 116800b99b8Sopenharmony_ci Run(state, UnwindLocal, &data); 117800b99b8Sopenharmony_ci} 118800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindStackLocal); 119800b99b8Sopenharmony_ci 120800b99b8Sopenharmony_ci/** 121800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindStackLocalCache 122800b99b8Sopenharmony_ci* @tc.desc: UnwindStack local cache 123800b99b8Sopenharmony_ci* @tc.type: FUNC 124800b99b8Sopenharmony_ci*/ 125800b99b8Sopenharmony_cistatic void BenchmarkUnwindStackLocalCache(benchmark::State& state) 126800b99b8Sopenharmony_ci{ 127800b99b8Sopenharmony_ci auto processMemory = unwindstack::Memory::CreateProcessMemoryCached(getpid()); 128800b99b8Sopenharmony_ci unwindstack::LocalMaps maps; 129800b99b8Sopenharmony_ci if (!maps.Parse()) { 130800b99b8Sopenharmony_ci state.SkipWithError("Failed to parse local maps."); 131800b99b8Sopenharmony_ci } 132800b99b8Sopenharmony_ci 133800b99b8Sopenharmony_ci UnwindData data = {.processMemory = processMemory, .maps = &maps, .isFillFrames = false}; 134800b99b8Sopenharmony_ci Run(state, UnwindLocal, &data); 135800b99b8Sopenharmony_ci} 136800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindStackLocalCache); 137800b99b8Sopenharmony_ci 138800b99b8Sopenharmony_ci/** 139800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindStackLocalFrames 140800b99b8Sopenharmony_ci* @tc.desc: UnwindStack local frames 141800b99b8Sopenharmony_ci* @tc.type: FUNC 142800b99b8Sopenharmony_ci*/ 143800b99b8Sopenharmony_cistatic void BenchmarkUnwindStackLocalFrames(benchmark::State& state) 144800b99b8Sopenharmony_ci{ 145800b99b8Sopenharmony_ci auto processMemory = unwindstack::Memory::CreateProcessMemory(getpid()); 146800b99b8Sopenharmony_ci unwindstack::LocalMaps maps; 147800b99b8Sopenharmony_ci if (!maps.Parse()) { 148800b99b8Sopenharmony_ci state.SkipWithError("Failed to parse local maps."); 149800b99b8Sopenharmony_ci } 150800b99b8Sopenharmony_ci 151800b99b8Sopenharmony_ci UnwindData data = {.processMemory = processMemory, .maps = &maps, .isFillFrames = true}; 152800b99b8Sopenharmony_ci Run(state, UnwindLocal, &data); 153800b99b8Sopenharmony_ci} 154800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindStackLocalFrames); 155800b99b8Sopenharmony_ci 156800b99b8Sopenharmony_ci/** 157800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindStackLocalFramesCache 158800b99b8Sopenharmony_ci* @tc.desc: UnwindStack local frames cache 159800b99b8Sopenharmony_ci* @tc.type: FUNC 160800b99b8Sopenharmony_ci*/ 161800b99b8Sopenharmony_cistatic void BenchmarkUnwindStackLocalFramesCache(benchmark::State& state) 162800b99b8Sopenharmony_ci{ 163800b99b8Sopenharmony_ci auto processMemory = unwindstack::Memory::CreateProcessMemoryCached(getpid()); 164800b99b8Sopenharmony_ci unwindstack::LocalMaps maps; 165800b99b8Sopenharmony_ci if (!maps.Parse()) { 166800b99b8Sopenharmony_ci state.SkipWithError("Failed to parse local maps."); 167800b99b8Sopenharmony_ci } 168800b99b8Sopenharmony_ci 169800b99b8Sopenharmony_ci UnwindData data = {.processMemory = processMemory, .maps = &maps, .isFillFrames = true}; 170800b99b8Sopenharmony_ci Run(state, UnwindLocal, &data); 171800b99b8Sopenharmony_ci} 172800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindStackLocalFramesCache);