mirror of
https://gitee.com/openharmony/developtools_profiler
synced 2024-11-23 15:00:17 +00:00
improve native daemon sa performance
Signed-off-by: zyxzyx <zhangyixin19@huawei.com>
This commit is contained in:
parent
23b1f9b4be
commit
69a65c2d8b
@ -113,6 +113,7 @@ struct alignas(8) ClientConfig { // 8 is 8 bit
|
||||
isBlocked = false;
|
||||
memtraceEnable = false;
|
||||
responseLibraryMode = false;
|
||||
freeEventOnlyAddrEnable = false;
|
||||
}
|
||||
|
||||
std::string ToString()
|
||||
@ -123,7 +124,8 @@ struct alignas(8) ClientConfig { // 8 is 8 bit
|
||||
<< ", mallocDisable:" << mallocDisable << ", mmapDisable:" << mmapDisable
|
||||
<< ", freeStackData:" << freeStackData << ", munmapStackData:" << munmapStackData
|
||||
<< ", fpunwind:" << fpunwind << ", isBlocked:" << isBlocked << ", memtraceEnable:" << memtraceEnable
|
||||
<< ", sampleInterval: " << sampleInterval << ", responseLibraryMode: " << responseLibraryMode;
|
||||
<< ", sampleInterval: " << sampleInterval << ", responseLibraryMode: " << responseLibraryMode
|
||||
<< ", freeEventOnlyAddrEnable: " << freeEventOnlyAddrEnable;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -140,14 +142,6 @@ struct alignas(8) ClientConfig { // 8 is 8 bit
|
||||
bool isBlocked = false;
|
||||
bool memtraceEnable = false;
|
||||
bool responseLibraryMode = false;
|
||||
bool freeEventOnlyAddrEnable = false;
|
||||
};
|
||||
|
||||
struct StandaloneRawStack {
|
||||
BaseStackRawData* stackConext; // points to the foundation type data
|
||||
uint8_t* stackData;
|
||||
int8_t* data; // fp mode data is ip, dwarf mode data is regs
|
||||
uint32_t stackSize;
|
||||
uint8_t fpDepth; // fp mode fpDepth is ip depth, dwarf mode is invalid
|
||||
};
|
||||
|
||||
#endif // HOOK_COMMON_H
|
@ -64,7 +64,7 @@ public:
|
||||
std::shared_ptr<StackPreprocess> stackPreprocess = nullptr;
|
||||
bool isRecordAccurately = false;
|
||||
};
|
||||
HookManager();
|
||||
HookManager() = default;
|
||||
bool RegisterAgentPlugin(const std::string& pluginPath);
|
||||
bool UnregisterAgentPlugin(const std::string& pluginPath);
|
||||
|
||||
@ -118,6 +118,7 @@ private:
|
||||
FILE* fpHookData_ {nullptr};
|
||||
std::vector<std::shared_ptr<HookManagerCtx>> hookCtx_;
|
||||
bool isSaService_{false};
|
||||
bool noDataQueue_{false};
|
||||
};
|
||||
}
|
||||
#endif // AGENT_MANAGER_H
|
@ -66,6 +66,7 @@ public:
|
||||
{
|
||||
isSaService_ = flag;
|
||||
}
|
||||
void TakeResultsFromShmem(const std::shared_ptr<EventNotifier>&, const std::shared_ptr<ShareMemoryBlock>&);
|
||||
|
||||
private:
|
||||
using CallFrame = OHOS::Developtools::NativeDaemon::CallFrame;
|
||||
@ -78,15 +79,16 @@ private:
|
||||
};
|
||||
|
||||
enum RecordStatisticsLimit : std::size_t {
|
||||
STATISTICS_MAP_SZIE = 2048,
|
||||
STATISTICS_PERIOD_DATA_SIZE = 256,
|
||||
ALLOC_ADDRMAMP_SIZE = 2048,
|
||||
STATISTICS_MAP_SZIE = 100000,
|
||||
STATISTICS_PERIOD_DATA_SIZE = 100000,
|
||||
ALLOC_ADDRMAMP_SIZE = 100000,
|
||||
};
|
||||
|
||||
private:
|
||||
void TakeResults();
|
||||
void SetHookData(RawStackPtr RawStack, std::vector<CallFrame>& callFrames,
|
||||
BatchNativeHookData& batchNativeHookData);
|
||||
void SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData);
|
||||
void WriteFrames(RawStackPtr RawStack, const std::vector<CallFrame>& callFrames);
|
||||
void SetFrameInfo(Frame& frame, CallFrame& callFrame);
|
||||
void ReportSymbolNameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData);
|
||||
@ -112,8 +114,11 @@ private:
|
||||
BatchNativeHookData& batchNativeHookData, T* event, uint32_t stackId);
|
||||
void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames,
|
||||
BatchNativeHookData& batchNativeHookData);
|
||||
void SetAllocStatisticsFrame(const RawStackPtr& rawStack, BatchNativeHookData& batchNativeHookData);
|
||||
bool SetFreeStatisticsData(uint64_t addr);
|
||||
void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false);
|
||||
void IntervalFlushRecordStatistics(BatchNativeHookData& stackData);
|
||||
bool HandleNoStackEvent(RawStackPtr& rawStack, BatchNativeHookData& stackData);
|
||||
unsigned LgFloor(unsigned long x);
|
||||
uint64_t PowCeil(uint64_t x);
|
||||
size_t ComputeAlign(size_t size);
|
||||
@ -139,7 +144,6 @@ private:
|
||||
// Key is ip , response_library_mode used
|
||||
std::unordered_map<uint64_t, uint32_t> responseLibraryMap_;
|
||||
std::chrono::seconds statisticsInterval_ {0};
|
||||
std::chrono::steady_clock::time_point lastStatisticsTime_;
|
||||
// Key is call stack id, value is recordstatistic data
|
||||
std::unordered_map<uint32_t, RecordStatistic> recordStatisticsMap_ {STATISTICS_MAP_SZIE};
|
||||
// Key is call stack id, value is recordstatistic data pointer
|
||||
|
@ -85,6 +85,8 @@ public:
|
||||
void FillMapsCache(std::string& currentFileName, std::shared_ptr<DfxMap> mapItem);
|
||||
void HandleMapInfo(uint64_t begin, uint64_t length, uint32_t flags, uint64_t offset, const std::string& filePath);
|
||||
void RemoveMaps(uint64_t addr);
|
||||
// threads
|
||||
VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = "");
|
||||
std::vector<uint64_t>& GetOfflineMaps()
|
||||
{
|
||||
return offlineMapAddr_;
|
||||
@ -112,9 +114,6 @@ public:
|
||||
#endif
|
||||
const bool loadSymboleWhenNeeded_ = true; // thie is a feature config
|
||||
void UpdateSymbols(std::string filename);
|
||||
// we don't know whether hap vma mapping is stand for a so
|
||||
// thus we need try to parse it first
|
||||
bool UpdateHapSymbols(std::shared_ptr<DfxMap> map);
|
||||
bool IsSymbolExist(const std::string& fileName);
|
||||
void DelSymbolFile(const std::string& fileName);
|
||||
void UpdateMaps(pid_t pid, pid_t tid);
|
||||
@ -176,8 +175,6 @@ private:
|
||||
// find synbols function name
|
||||
void MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame);
|
||||
|
||||
// threads
|
||||
VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = "");
|
||||
std::string ReadThreadName(pid_t tid);
|
||||
VirtualThread &CreateThread(pid_t pid, pid_t tid);
|
||||
|
||||
|
@ -40,7 +40,6 @@ namespace {
|
||||
const int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
|
||||
const int PAGE_BYTES = 4096;
|
||||
std::shared_ptr<Writer> g_buffWriter;
|
||||
constexpr uint32_t MAX_BUFFER_SIZE = 10 * 1024;
|
||||
const std::string STARTUP = "startup:";
|
||||
const std::string PARAM_NAME = "libc.hook_mode";
|
||||
const int SIGNAL_START_HOOK = 36;
|
||||
@ -99,7 +98,7 @@ bool HookManager::CheckProcessName()
|
||||
int pidValue = -1;
|
||||
const std::string processName = hookConfig_.process_name();
|
||||
bool isExist = COMMON::IsProcessExist(processName, pidValue);
|
||||
if (hookConfig_.startup_mode() || !isExist) {
|
||||
if (hookConfig_.startup_mode() && !isExist) {
|
||||
HILOG_INFO(LOG_CORE, "Wait process %s start or restart, set param", hookConfig_.process_name().c_str());
|
||||
std::string cmd = STARTUP + hookConfig_.process_name();
|
||||
int ret = SystemSetParameter(PARAM_NAME.c_str(), cmd.c_str());
|
||||
@ -125,8 +124,6 @@ bool HookManager::CheckProcessName()
|
||||
return true;
|
||||
}
|
||||
|
||||
HookManager::HookManager() : buffer_(new (std::nothrow) uint8_t[MAX_BUFFER_SIZE]) { }
|
||||
|
||||
void HookManager::SetCommandPoller(const std::shared_ptr<CommandPoller>& p)
|
||||
{
|
||||
commandPoller_ = p;
|
||||
@ -236,9 +233,6 @@ bool HookManager::HandleHookContext(const std::shared_ptr<HookManagerCtx>& ctx)
|
||||
|
||||
ctx->eventPoller->Init();
|
||||
ctx->eventPoller->Start();
|
||||
ctx->eventPoller->AddFileDescriptor(
|
||||
ctx->eventNotifier->GetFd(),
|
||||
std::bind(&HookManager::ReadShareMemory, this, ctx));
|
||||
|
||||
HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", ctx->shareMemoryBlock->GetfileDescriptor(),
|
||||
ctx->eventNotifier->GetFd());
|
||||
@ -250,11 +244,23 @@ bool HookManager::HandleHookContext(const std::shared_ptr<HookManagerCtx>& ctx)
|
||||
hookConfig_.fp_unwind(), hookConfig_.max_stack_depth(), ctx->isRecordAccurately);
|
||||
HILOG_INFO(LOG_CORE, "hookConfig offline_symbolization = %d", hookConfig_.offline_symbolization());
|
||||
|
||||
ctx->stackData = std::make_shared<StackDataRepeater>(STACK_DATA_SIZE);
|
||||
CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL");
|
||||
clockid_t pluginDataClockId = COMMON::GetClockId(hookConfig_.clock());
|
||||
ctx->stackPreprocess = std::make_shared<StackPreprocess>(ctx->stackData, hookConfig_, pluginDataClockId,
|
||||
if (noDataQueue_) {
|
||||
ctx->stackPreprocess = std::make_shared<StackPreprocess>(nullptr, hookConfig_, pluginDataClockId,
|
||||
fpHookData_, isHookStandalone_);
|
||||
ctx->eventPoller->AddFileDescriptor(
|
||||
ctx->eventNotifier->GetFd(),
|
||||
std::bind(&StackPreprocess::TakeResultsFromShmem, ctx->stackPreprocess,
|
||||
ctx->eventNotifier, ctx->shareMemoryBlock));
|
||||
} else {
|
||||
ctx->stackData = std::make_shared<StackDataRepeater>(STACK_DATA_SIZE);
|
||||
CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL");
|
||||
ctx->stackPreprocess = std::make_shared<StackPreprocess>(ctx->stackData, hookConfig_, pluginDataClockId,
|
||||
fpHookData_, isHookStandalone_);
|
||||
ctx->eventPoller->AddFileDescriptor(
|
||||
ctx->eventNotifier->GetFd(),
|
||||
std::bind(&HookManager::ReadShareMemory, this, ctx));
|
||||
}
|
||||
CHECK_TRUE(ctx->stackPreprocess != nullptr, false, "Create StackPreprocess FAIL");
|
||||
ctx->stackPreprocess->SetWriter(g_buffWriter);
|
||||
ctx->stackPreprocess->SetSaServiceFlag(isSaService_);
|
||||
@ -321,6 +327,12 @@ bool HookManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& c
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hookConfig_.fp_unwind() && hookConfig_.record_accurately()
|
||||
&& hookConfig_.blocked() && hookConfig_.offline_symbolization()
|
||||
&& hookConfig_.statistics_interval() > 0
|
||||
&& hookConfig_.sample_interval() > 1) {
|
||||
noDataQueue_ = true;
|
||||
}
|
||||
for (const auto& item : hookCtx_) {
|
||||
CHECK_TRUE(HandleHookContext(item), false, "handle hook context failed"); // Create the required resources.
|
||||
}
|
||||
@ -328,6 +340,9 @@ bool HookManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& c
|
||||
if (!isSaService_) { // SA mode will start HookService in the service.
|
||||
ClientConfig clientConfig;
|
||||
GetClientConfig(clientConfig);
|
||||
if(noDataQueue_) {
|
||||
clientConfig.freeEventOnlyAddrEnable = true;
|
||||
}
|
||||
std::string clientConfigStr = clientConfig.ToString();
|
||||
HILOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str());
|
||||
hookService_ = std::make_shared<HookService>(clientConfig, shared_from_this());
|
||||
@ -554,7 +569,9 @@ void HookManager::StartPluginSession()
|
||||
continue;
|
||||
}
|
||||
HILOG_ERROR(LOG_CORE, "StartPluginSession name: %s", item->processName.c_str());
|
||||
item->stackPreprocess->StartTakeResults();
|
||||
if (!noDataQueue_) {
|
||||
item->stackPreprocess->StartTakeResults();
|
||||
}
|
||||
if (item->pid > 0) {
|
||||
HILOG_INFO(LOG_CORE, "start command : send 36 signal to process %d", item->pid);
|
||||
if (kill(item->pid, SIGNAL_START_HOOK) == -1) {
|
||||
|
@ -132,6 +132,10 @@ bool StackPreprocess::StartTakeResults()
|
||||
bool StackPreprocess::StopTakeResults()
|
||||
{
|
||||
HILOG_INFO(LOG_CORE, "start StopTakeResults");
|
||||
if(!dataRepeater_) {
|
||||
isStopTakeData_ = true;
|
||||
return true;
|
||||
}
|
||||
CHECK_NOTNULL(dataRepeater_, false, "data repeater null");
|
||||
CHECK_TRUE(thread_.get_id() != std::thread::id(), false, "thread invalid");
|
||||
|
||||
@ -146,6 +150,97 @@ bool StackPreprocess::StopTakeResults()
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void StackPreprocess::IntervalFlushRecordStatistics(BatchNativeHookData& stackData)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
FlushData(stackData);
|
||||
}
|
||||
// interval reporting statistics
|
||||
if (hookConfig_.statistics_interval() > 0) {
|
||||
static auto lastStatisticsTime = std::chrono::steady_clock::now();
|
||||
auto currentTime = std::chrono::steady_clock::now();
|
||||
auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(currentTime - lastStatisticsTime);
|
||||
if (elapsedTime >= statisticsInterval_) {
|
||||
lastStatisticsTime = currentTime;
|
||||
FlushRecordStatistics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StackPreprocess::HandleNoStackEvent(RawStackPtr& rawData, BatchNativeHookData& stackData)
|
||||
{
|
||||
if (rawData->stackConext->type == MMAP_FILE_TYPE) {
|
||||
BaseStackRawData* mmapRawData = rawData->stackConext;
|
||||
std::string filePath(reinterpret_cast<char *>(rawData->data));
|
||||
COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid);
|
||||
HILOG_DEBUG(LOG_CORE, "MMAP_FILE_TYPE curMmapAddr=%p, MAP_FIXED=%d, "
|
||||
"PROT_EXEC=%d, offset=%" PRIu64 ", filePath=%s",
|
||||
mmapRawData->addr, mmapRawData->mmapArgs.flags & MAP_FIXED,
|
||||
mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data());
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
runtime_instance->HandleMapInfo(reinterpret_cast<uint64_t>(mmapRawData->addr),
|
||||
mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset, filePath);
|
||||
}
|
||||
flushBasicData_ = true;
|
||||
} else if (rawData->stackConext->type == THREAD_NAME_MSG) {
|
||||
std::string threadName = reinterpret_cast<char*>(rawData->data);
|
||||
ReportThreadNameMap(rawData->stackConext->tid, threadName, stackData);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr<EventNotifier>& eventNotifier,
|
||||
const std::shared_ptr<ShareMemoryBlock>& shareMemoryBlock)
|
||||
{
|
||||
eventNotifier->Take();
|
||||
StackDataRepeater::RawStack rawStack;
|
||||
RawStackPtr rawData(&rawStack, [](StackDataRepeater::RawStack* del) {});
|
||||
while (!isStopTakeData_) {
|
||||
BatchNativeHookData stackData;
|
||||
bool ret = shareMemoryBlock->TakeData(
|
||||
[&](const int8_t data[], uint32_t size) -> bool {
|
||||
if (size == sizeof(uint64_t)) {
|
||||
uint64_t addr = *reinterpret_cast<uint64_t *>(const_cast<int8_t *>(data));
|
||||
SetFreeStatisticsData(addr);
|
||||
return true;
|
||||
}
|
||||
CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!");
|
||||
rawData->stackConext = reinterpret_cast<BaseStackRawData *>(const_cast<int8_t *>(data));
|
||||
rawData->data = reinterpret_cast<uint8_t*>(const_cast<int8_t *>(data)) + sizeof(BaseStackRawData);
|
||||
rawData->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t);
|
||||
if (isStopTakeData_) {
|
||||
return false;
|
||||
} else if (rawData->stackConext->type == MEMORY_TAG) {
|
||||
std::string tagName = reinterpret_cast<char*>(rawData->data);
|
||||
SaveMemTag(rawData->stackConext->tagId, tagName);
|
||||
return true;
|
||||
} else if(HandleNoStackEvent(rawData, stackData)) {
|
||||
if(rawData->stackConext->type == THREAD_NAME_MSG) {
|
||||
FlushData(stackData);
|
||||
}
|
||||
return true;
|
||||
} else if (rawData->stackConext->type == MUNMAP_MSG) {
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
runtime_instance->UpdateThread(rawData->stackConext->pid, rawData->stackConext->tid);
|
||||
}
|
||||
SetHookData(rawData, stackData);
|
||||
IntervalFlushRecordStatistics(stackData);
|
||||
return true;
|
||||
});
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StackPreprocess::TakeResults()
|
||||
{
|
||||
if (!dataRepeater_) {
|
||||
@ -172,30 +267,12 @@ void StackPreprocess::TakeResults()
|
||||
if (!rawData || isStopTakeData_) {
|
||||
break;
|
||||
}
|
||||
if (rawData->stackConext->type == MMAP_FILE_TYPE) {
|
||||
BaseStackRawData* mmapRawData = rawData->stackConext;
|
||||
std::string filePath(reinterpret_cast<char *>(rawData->data));
|
||||
COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid);
|
||||
HILOG_DEBUG(LOG_CORE, "MMAP_FILE_TYPE curMmapAddr=%p, MAP_FIXED=%d, "
|
||||
"PROT_EXEC=%d, offset=%" PRIu64 ", filePath=%s",
|
||||
mmapRawData->addr, mmapRawData->mmapArgs.flags & MAP_FIXED,
|
||||
mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data());
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
runtime_instance->HandleMapInfo(reinterpret_cast<uint64_t>(mmapRawData->addr),
|
||||
mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset, filePath);
|
||||
}
|
||||
flushBasicData_ = true;
|
||||
if (HandleNoStackEvent(rawData, stackData)) {
|
||||
continue;
|
||||
} else if (rawData->stackConext->type == MUNMAP_MSG) {
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
|
||||
}
|
||||
if (rawData->stackConext->type == THREAD_NAME_MSG) {
|
||||
std::string threadName = reinterpret_cast<char*>(rawData->data);
|
||||
ReportThreadNameMap(rawData->stackConext->tid, threadName, stackData);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rawData->reportFlag) {
|
||||
ignoreCnts_++;
|
||||
@ -282,20 +359,7 @@ void StackPreprocess::TakeResults()
|
||||
if (hookConfig_.save_file() && hookConfig_.file_name() != "" && !isHookStandaloneSerialize_) {
|
||||
continue;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
FlushData(stackData);
|
||||
}
|
||||
|
||||
// interval reporting statistics
|
||||
if (hookConfig_.statistics_interval() > 0) {
|
||||
auto currentTime = std::chrono::steady_clock::now();
|
||||
auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(currentTime - lastStatisticsTime_);
|
||||
if (elapsedTime >= statisticsInterval_) {
|
||||
lastStatisticsTime_ = currentTime;
|
||||
FlushRecordStatistics();
|
||||
}
|
||||
}
|
||||
IntervalFlushRecordStatistics(stackData);
|
||||
}
|
||||
HILOG_INFO(LOG_CORE, "TakeResults thread %d, exit!", gettid());
|
||||
}
|
||||
@ -465,6 +529,58 @@ void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack,
|
||||
}
|
||||
}
|
||||
|
||||
void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack,
|
||||
BatchNativeHookData& batchNativeHookData)
|
||||
{
|
||||
callStack_.resize(rawStack->fpDepth);
|
||||
if (memcpy_s(callStack_.data(), sizeof(uint64_t) * rawStack->fpDepth,
|
||||
rawStack->data, sizeof(uint64_t) * rawStack->fpDepth) != EOK) {
|
||||
HILOG_ERROR(LOG_CORE, "memcpy_s callStack_ failed");
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(mtx_);
|
||||
// by call stack id set alloc statistics data.
|
||||
uint32_t stackId = FindCallStackId(callStack_);
|
||||
if (stackId > 0) {
|
||||
SetAllocStatisticsData(rawStack, stackId, true);
|
||||
} else {
|
||||
stackId = SetCallStackMap(batchNativeHookData);
|
||||
SetAllocStatisticsData(rawStack, stackId);
|
||||
}
|
||||
}
|
||||
|
||||
void StackPreprocess::SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData)
|
||||
{
|
||||
if (flushBasicData_) {
|
||||
SetMapsInfo(rawStack->stackConext->pid);
|
||||
flushBasicData_ = false;
|
||||
}
|
||||
// statistical reporting must is compressed and accurate.
|
||||
switch (rawStack->stackConext->type) {
|
||||
case FREE_MSG:
|
||||
case MUNMAP_MSG:
|
||||
case MEMORY_UNUSING_MSG: {
|
||||
SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr);
|
||||
break;
|
||||
}
|
||||
case MALLOC_MSG:
|
||||
case MMAP_MSG:
|
||||
case MMAP_FILE_PAGE_MSG:
|
||||
case MEMORY_USING_MSG: {
|
||||
SetAllocStatisticsFrame(rawStack, batchNativeHookData);
|
||||
break;
|
||||
}
|
||||
case PR_SET_VMA_MSG: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
HILOG_ERROR(LOG_CORE, "statistics event type: error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void StackPreprocess::SetHookData(RawStackPtr rawStack,
|
||||
std::vector<CallFrame>& callFrames, BatchNativeHookData& batchNativeHookData)
|
||||
{
|
||||
@ -489,6 +605,9 @@ void StackPreprocess::SetHookData(RawStackPtr rawStack,
|
||||
SetAllocStatisticsFrame(rawStack, callFrames, batchNativeHookData);
|
||||
break;
|
||||
}
|
||||
case PR_SET_VMA_MSG: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
HILOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type);
|
||||
break;
|
||||
@ -823,22 +942,19 @@ void StackPreprocess::Flush(const uint8_t* src, size_t size)
|
||||
HILOG_ERROR(LOG_CORE, "Flush src is nullptr");
|
||||
return;
|
||||
}
|
||||
if (isSaService_) {
|
||||
ProfilerPluginData pluginData;
|
||||
pluginData.set_name("nativehook");
|
||||
pluginData.set_version("1.02");
|
||||
pluginData.set_status(0);
|
||||
pluginData.set_data(src, size);
|
||||
struct timespec ts;
|
||||
clock_gettime(pluginDataClockId_, &ts);
|
||||
pluginData.set_clock_id(static_cast<ProfilerPluginData_ClockId>(pluginDataClockId_));
|
||||
pluginData.set_tv_sec(ts.tv_sec);
|
||||
pluginData.set_tv_nsec(ts.tv_nsec);
|
||||
pluginData.SerializeToArray(buffer_.get(), pluginData.ByteSizeLong());
|
||||
size = pluginData.ByteSizeLong();
|
||||
}
|
||||
ProfilerPluginData pluginData;
|
||||
pluginData.set_name("nativehook");
|
||||
pluginData.set_version("1.02");
|
||||
pluginData.set_status(0);
|
||||
pluginData.set_data(src, size);
|
||||
struct timespec ts;
|
||||
clock_gettime(pluginDataClockId_, &ts);
|
||||
pluginData.set_clock_id(static_cast<ProfilerPluginData_ClockId>(pluginDataClockId_));
|
||||
pluginData.set_tv_sec(ts.tv_sec);
|
||||
pluginData.set_tv_nsec(ts.tv_nsec);
|
||||
pluginData.SerializeToArray(buffer_.get(), pluginData.ByteSizeLong());
|
||||
|
||||
writer_->Write(buffer_.get(), size);
|
||||
writer_->Write(buffer_.get(), pluginData.ByteSizeLong());
|
||||
writer_->Flush();
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,37 @@ constexpr int RESPONSE_LIBRARY_MODE_DEPTH = 5;
|
||||
static bool g_isPidChanged = false;
|
||||
static struct mallinfo2 g_miStart = {0};
|
||||
std::vector<std::pair<uint64_t, uint64_t>> g_filterStaLibRange;
|
||||
constexpr int MAX_BITPOOL_SIZE = 100 * 1024;
|
||||
struct Bitpool {
|
||||
std::atomic<uint32_t> slot;
|
||||
};
|
||||
Bitpool addressChecker[MAX_BITPOOL_SIZE] = {{0}};
|
||||
|
||||
inline static uint32_t addrHash(uint32_t h)
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
return h;
|
||||
}
|
||||
|
||||
inline void Addr2Bitpool(void* addr)
|
||||
{
|
||||
uint32_t val = addrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * 32);
|
||||
addressChecker[val / 32].slot |= (0x1 << (val % 32));
|
||||
}
|
||||
|
||||
inline bool IsAddrExist(void* addr)
|
||||
{
|
||||
uint32_t val = addrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * 32);
|
||||
if (addressChecker[val / 32].slot.load() & (0x1 << (val % 32))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const MallocDispatchType* GetDispatch()
|
||||
{
|
||||
return g_dispatch.load(std::memory_order_relaxed);
|
||||
@ -357,6 +388,9 @@ void* hook_malloc(void* (*fn)(size_t), size_t size)
|
||||
rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
|
||||
rawdata.mallocSize = size;
|
||||
rawdata.addr = ret;
|
||||
if (g_ClientConfig.sampleInterval >= 256) {
|
||||
Addr2Bitpool(ret);
|
||||
}
|
||||
int realSize = 0;
|
||||
if (g_ClientConfig.fpunwind) {
|
||||
realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
|
||||
@ -431,6 +465,9 @@ void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size)
|
||||
rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
|
||||
rawdata.mallocSize = number * size;
|
||||
rawdata.addr = pRet;
|
||||
if (g_ClientConfig.sampleInterval >= 256) {
|
||||
Addr2Bitpool(pRet);
|
||||
}
|
||||
std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
|
||||
auto holder = weakClient.lock();
|
||||
if (holder != nullptr) {
|
||||
@ -507,6 +544,9 @@ void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size)
|
||||
rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
|
||||
rawdata.mallocSize = size;
|
||||
rawdata.addr = pRet;
|
||||
if (g_ClientConfig.sampleInterval >= 256) {
|
||||
Addr2Bitpool(pRet);
|
||||
}
|
||||
std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
|
||||
auto holder = weakClient.lock();
|
||||
if (holder != nullptr) {
|
||||
@ -546,6 +586,20 @@ void hook_free(void (*free_func)(void*), void* p)
|
||||
if (g_ClientConfig.mallocDisable || IsPidChanged()) {
|
||||
return;
|
||||
}
|
||||
if (g_ClientConfig.sampleInterval >= 256) {
|
||||
if (!IsAddrExist(p)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g_ClientConfig.freeEventOnlyAddrEnable) {
|
||||
uint64_t addr = reinterpret_cast<uint64_t>(p);
|
||||
std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
|
||||
auto holder = weakClient.lock();
|
||||
if (holder != nullptr) {
|
||||
holder->SendStackWithPayload(&addr, sizeof(addr), nullptr, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
StackRawData rawdata = {{{{0}}}};
|
||||
const char* stackptr = nullptr;
|
||||
const char* stackendptr = nullptr;
|
||||
|
@ -22,10 +22,8 @@
|
||||
|
||||
#include "buffer_splitter.h"
|
||||
#include "logging.h"
|
||||
#include "parameters.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#pragma clang optimize off
|
||||
|
||||
@ -73,9 +71,6 @@ public:
|
||||
outFile_ = DEFAULT_PATH + "hooktest_"+ outFileType_ + mode_[modeIndex_] + ".txt";
|
||||
int processNum = fork();
|
||||
if (processNum == 0) {
|
||||
int waitProcMills = 300;
|
||||
OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
|
||||
command_.push_back(const_cast<char*>(DEFAULT_NATIVE_DAEMON_PATH.c_str()));
|
||||
command_.push_back(const_cast<char*>("-o"));
|
||||
command_.push_back(const_cast<char*>(outFile_.c_str()));
|
||||
@ -901,11 +896,12 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Lev
|
||||
*/
|
||||
HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Level3)
|
||||
{
|
||||
for (size_t i = 1; i < 2; ++i) { // 1 is fp mode, response_library_mode only fp mode is used
|
||||
for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode
|
||||
unwindDepth_ = 6;
|
||||
outFileType_ = "responseLibraryMode";
|
||||
modeIndex_ = i;
|
||||
responseLibraryMode_ = true;
|
||||
offlineSymbolization_ = true;
|
||||
StartMallocProcess();
|
||||
StartAndStopHook();
|
||||
|
||||
@ -913,24 +909,19 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Lev
|
||||
infile.open(outFile_, std::ios::in);
|
||||
EXPECT_TRUE(infile.is_open());
|
||||
std::string buf;
|
||||
uint16_t ipCount = 0;
|
||||
bool foundSymbolTab = false;
|
||||
bool foundMapsInfo = false;
|
||||
|
||||
while (getline(infile, buf)) {
|
||||
if (buf.find("stack_map") != std::string::npos) {
|
||||
while (getline(infile, buf)) {
|
||||
if (buf.find("ip") != std::string::npos) {
|
||||
++ipCount;
|
||||
continue;
|
||||
} else if (buf.find("}") != std::string::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buf.find("symbol_tab") != std::string::npos) {
|
||||
foundSymbolTab = true;
|
||||
}
|
||||
if (ipCount > 0) {
|
||||
break;
|
||||
if (buf.find("maps_info") != std::string::npos) {
|
||||
foundMapsInfo = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(ipCount == 1); // response_library_mode callstack depth only is 1
|
||||
EXPECT_TRUE(foundSymbolTab);
|
||||
EXPECT_TRUE(foundMapsInfo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -347,7 +347,6 @@ bool ShareMemoryBlock::TakeData(const DataHandler& func, bool isProtobufSerializ
|
||||
CHECK_NOTNULL(header_, false, "header not ready!");
|
||||
CHECK_TRUE(static_cast<bool>(func), false, "func invalid!");
|
||||
|
||||
PthreadLocker locker(header_->info.mutex_);
|
||||
auto size = GetDataSize();
|
||||
if (size == 0) {
|
||||
return false;
|
||||
@ -443,6 +442,15 @@ bool ShareMemoryBlock::PutWithPayloadSync(const int8_t* header, uint32_t headerS
|
||||
pthread_mutex_unlock(&header_->info.mutex_);
|
||||
return true;
|
||||
}
|
||||
void ShareMemoryBlock::ClearShareMemoryBlock()
|
||||
{
|
||||
// clear header infos
|
||||
PthreadLocker locker(header_->info.mutex_);
|
||||
header_->info.readOffset_ = 0;
|
||||
header_->info.writeOffset_ = 0;
|
||||
header_->info.bytesCount_ = 0;
|
||||
header_->info.chunkCount_ = 0;
|
||||
}
|
||||
|
||||
void ShareMemoryBlock::UseMemory(int32_t size)
|
||||
{
|
||||
@ -541,4 +549,4 @@ bool ShareMemoryBlock::Seek(uint32_t pos)
|
||||
void ShareMemoryBlock::ResetPos()
|
||||
{
|
||||
messageWriteOffset_ = PIECE_HEAD_LEN;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user