mirror of
https://gitee.com/openharmony/developtools_profiler
synced 2024-11-23 15:00:17 +00:00
!1292 native daemon sa 提升性能
Merge pull request !1292 from zhangyixin/master
This commit is contained in:
commit
f8dd27ce0b
@ -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_;
|
||||
@ -176,8 +178,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;
|
||||
@ -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;
|
||||
|
@ -69,6 +69,10 @@ constexpr int STATUS_LINE_SIZE = 512;
|
||||
constexpr int PID_NAMESPACE_ID = 1; // 1: pid is 1 after pid namespace used
|
||||
constexpr int FD_PATH_LENGTH = 64;
|
||||
constexpr int MIN_SAMPLER_INTERVAL = 1;
|
||||
constexpr int FIRST_HASH = 16;
|
||||
constexpr int SECOND_HASH = 13;
|
||||
constexpr int THRESHOLD = 256;
|
||||
constexpr int DIVIDE_VAL = 32;
|
||||
//5: fp mode is used, response_library_mode maximum stack depth
|
||||
#if defined(__aarch64__)
|
||||
constexpr int RESPONSE_LIBRARY_MODE_DEPTH = 5;
|
||||
@ -76,6 +80,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 g_addressChecker[MAX_BITPOOL_SIZE] = {{0}};
|
||||
|
||||
inline static uint32_t AddrHash(uint32_t h)
|
||||
{
|
||||
h ^= h >> FIRST_HASH;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> SECOND_HASH;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> FIRST_HASH;
|
||||
return h;
|
||||
}
|
||||
|
||||
inline void Addr2Bitpool(void* addr)
|
||||
{
|
||||
uint32_t val = AddrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * DIVIDE_VAL);
|
||||
g_addressChecker[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL));
|
||||
}
|
||||
|
||||
inline bool IsAddrExist(void* addr)
|
||||
{
|
||||
uint32_t val = AddrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * DIVIDE_VAL);
|
||||
if (g_addressChecker[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const MallocDispatchType* GetDispatch()
|
||||
{
|
||||
return g_dispatch.load(std::memory_order_relaxed);
|
||||
@ -357,6 +392,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 >= THRESHOLD) {
|
||||
Addr2Bitpool(ret);
|
||||
}
|
||||
int realSize = 0;
|
||||
if (g_ClientConfig.fpunwind) {
|
||||
realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
|
||||
@ -431,6 +469,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 >= THRESHOLD) {
|
||||
Addr2Bitpool(pRet);
|
||||
}
|
||||
std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
|
||||
auto holder = weakClient.lock();
|
||||
if (holder != nullptr) {
|
||||
@ -507,6 +548,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 >= THRESHOLD) {
|
||||
Addr2Bitpool(pRet);
|
||||
}
|
||||
std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
|
||||
auto holder = weakClient.lock();
|
||||
if (holder != nullptr) {
|
||||
@ -546,6 +590,20 @@ void hook_free(void (*free_func)(void*), void* p)
|
||||
if (g_ClientConfig.mallocDisable || IsPidChanged()) {
|
||||
return;
|
||||
}
|
||||
if (g_ClientConfig.sampleInterval >= THRESHOLD) {
|
||||
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;
|
||||
|
@ -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;
|
||||
@ -541,4 +540,4 @@ bool ShareMemoryBlock::Seek(uint32_t pos)
|
||||
void ShareMemoryBlock::ResetPos()
|
||||
{
|
||||
messageWriteOffset_ = PIECE_HEAD_LEN;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user