Merge branch 'master' of gitee.com:openharmony/developtools_profiler into master

Signed-off-by: wenlong_12 <wenlong12@huawei.com>
This commit is contained in:
wenlong_12 2024-01-05 00:55:22 +00:00 committed by Gitee
commit 5ebb0e5b91
22 changed files with 421 additions and 115 deletions

View File

@ -80,6 +80,7 @@ ohos_source_set("hiprofiler_base") {
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",
"c_utils:utils",
"init:libbegetutil",
"ipc:ipc_core",
"os_account:os_account_innerkits",
"samgr:samgr_proxy",

View File

@ -46,5 +46,6 @@ std::string GetClockStr(const int32_t clockId);
void AdaptSandboxPath(std::string& filePath, int pid);
int32_t GetPackageUid(const std::string &name);
bool GetCurrentUserId(int32_t &userId);
bool IsBetaVersion();
} // COMMON
#endif // COMMON_H

View File

@ -21,6 +21,8 @@
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <parameter.h>
#include <parameters.h>
#include <sstream>
#include <sys/file.h>
#include <sys/types.h>
@ -64,6 +66,7 @@ const int FILE_PATH_SIZE = 512;
const int BUFFER_SIZE = 1024;
const int INVALID_PID = -1;
constexpr int32_t EC_INVALID_VALUE = -2;
const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype";
}
bool IsProcessRunning(int& lockFileFd)
@ -564,4 +567,16 @@ int32_t GetPackageUid(const std::string& name)
PROFILER_LOG_INFO(LOG_CORE, "pkgname is: %s, uid is : %d", name.c_str(), uid);
return uid;
}
bool IsBetaVersion()
{
int ret = static_cast<int>(FindParameter(KEY_HIVIEW_USER_TYPE.c_str()));
if (ret == -1) {
HILOG_INFO(LOG_CORE, "user type is not exist");
return true;
}
std::string userType = OHOS::system::GetParameter(KEY_HIVIEW_USER_TYPE, "");
HILOG_INFO(LOG_CORE, "user type is:%s", userType.c_str());
return userType == "beta";
}
} // namespace COMMON

View File

@ -461,6 +461,9 @@ bool CheckProcessExit(const std::string& processName, int& pid)
void KillDependentProcess()
{
constexpr int waitProcMills = 300;
OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
if (getuid() == 0) {
// if pid is equal to -1, need to get pid first.
if (g_nativeDaemonPid == -1) {

View File

@ -370,9 +370,10 @@ template <typename T, typename S> void MemoryDataPlugin::WriteMemoryData(T& memo
WriteGpuMemInfo(memoryDataProto);
}
WriteDumpProcessInfo(memoryDataProto);
if (protoConfig_.report_gpu_dump_info()) {
WriteGpuDumpInfo(memoryDataProto);
WriteDumpProcessInfo(memoryDataProto);
WriteManagerServiceInfo(memoryDataProto);
WriteProfileMemInfo(memoryDataProto);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
@ -128,8 +127,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;
@ -239,9 +236,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));
PROFILER_LOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", ctx->shareMemoryBlock->GetfileDescriptor(),
ctx->eventNotifier->GetFd());
@ -253,11 +247,23 @@ bool HookManager::HandleHookContext(const std::shared_ptr<HookManagerCtx>& ctx)
hookConfig_.fp_unwind(), hookConfig_.max_stack_depth(), ctx->isRecordAccurately);
PROFILER_LOG_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_);
@ -324,6 +330,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.
}
@ -331,6 +343,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();
PROFILER_LOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str());
hookService_ = std::make_shared<HookService>(clientConfig, shared_from_this());
@ -557,7 +572,9 @@ void HookManager::StartPluginSession()
continue;
}
PROFILER_LOG_ERROR(LOG_CORE, "StartPluginSession name: %s", item->processName.c_str());
item->stackPreprocess->StartTakeResults();
if (!noDataQueue_) {
item->stackPreprocess->StartTakeResults();
}
if (item->pid > 0) {
PROFILER_LOG_INFO(LOG_CORE, "start command : send 36 signal to process %d", item->pid);
if (kill(item->pid, SIGNAL_START_HOOK) == -1) {

View File

@ -235,6 +235,10 @@ int main(int argc, char* argv[])
}
if (argc > 1) {
if (!COMMON::IsBetaVersion()) {
printf("memory profiler only support in beta version\n");
return 0;
}
if (argc == 2 && strcmp(argv[1], "sa") == 0) {
if (!OHOS::Developtools::NativeDaemon::NativeMemoryProfilerSaService::StartServiceAbility()) {
return 0;

View File

@ -132,6 +132,10 @@ bool StackPreprocess::StartTakeResults()
bool StackPreprocess::StopTakeResults()
{
PROFILER_LOG_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);
PROFILER_LOG_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_++;
@ -283,20 +360,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);
}
PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, exit!", gettid());
}
@ -466,6 +530,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)
{
@ -490,6 +606,9 @@ void StackPreprocess::SetHookData(RawStackPtr rawStack,
SetAllocStatisticsFrame(rawStack, callFrames, batchNativeHookData);
break;
}
case PR_SET_VMA_MSG: {
break;
}
default: {
PROFILER_LOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type);
break;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -37,13 +37,9 @@ std::map<std::string, std::string> Network::ItemData()
return result;
}
std::map<std::string, std::string> Network::GetNetworkInfo() const
std::map<std::string, std::string> Network::GetNetworkInfo()
{
std::map<std::string, std::string> networkInfo;
long long allTx = 0;
long long allRx = 0;
long long curTx = 0;
long long curRx = 0;
char buff[LARGE_BUFF_MAX_LEN];
FILE *fp = fopen("/proc/net/dev", "r");
if (fp == nullptr) {
@ -61,8 +57,33 @@ std::map<std::string, std::string> Network::GetNetworkInfo() const
}
}
fclose(fp);
networkInfo["networkUp"] = std::to_string(allTx);
networkInfo["networkDown"] = std::to_string(allRx);
if (isFirst) {
networkInfo["networkUp"] = std::to_string(prevTx);
networkInfo["networkDown"] = std::to_string(prevRx);
isFirst = false;
prevTx = allTx;
prevRx = allRx;
allTx = 0;
allRx = 0;
return networkInfo;
}
if ((allTx == 0 && allRx == 0) || (allTx <= prevTx && allRx <= prevRx)) {
networkInfo["networkUp"] = "0";
networkInfo["networkDown"] = "0";
prevTx = allTx;
prevRx = allRx;
allTx = 0;
allRx = 0;
return networkInfo;
}
diffTx = allTx - prevTx;
prevTx = allTx;
diffRx = allRx - prevRx;
prevRx = allRx;
allTx = 0;
allRx = 0;
networkInfo["networkUp"] = std::to_string(diffTx);
networkInfo["networkDown"] = std::to_string(diffRx);
return networkInfo;
}
}

View File

@ -31,7 +31,7 @@ int ClientControl::SocketStart(std::string args)
read(clientSocket, buffer, numBuff);
send(clientSocket, message1, strlen(message1), 0);
read(clientSocket, buffer, numBuff);
if (strcmp(buffer, "start::true") == 0) {
if (strcmp(buffer, "start::True") == 0) {
std::cout << "SP_daemon Collection begins" << std::endl;
} else {
std::cout << "SP_daemon Collection begins failed" << std::endl;
@ -44,7 +44,7 @@ int ClientControl::SocketStop()
OHOS::SmartPerf::ClientControl::InitSocket();
send(clientSocket, message2, strlen(message2), 0);
read(clientSocket, buffer, numBuff);
if (strcmp(buffer, "stop::true") == 0) {
if (strcmp(buffer, "stop::True") == 0) {
std::cout << "SP_daemon Collection ended" << std::endl;
std::cout << "Output Path: data/local/tmp/smartperf/1/t_index_info.csv" << std::endl;
} else {

View File

@ -18,6 +18,7 @@
#include <cstring>
#include <map>
#include <sstream>
#include <future>
#include "include/control_call_cmd.h"
#include "include/startup_delay.h"
#include "include/parse_trace.h"
@ -54,8 +55,6 @@ std::string ControlCallCmd::GetResult(std::vector<std::string> v)
result = SmartPerf::ControlCallCmd::SlideFps(v);
} else if (v[typeName] == "pagefps") {
result = SmartPerf::ControlCallCmd::PageFps();
} else if (v[typeName] == "FPS") {
result = SmartPerf::ControlCallCmd::SlideFPS(v);
} else if (v[typeName] == "startFrame") {
result = SmartPerf::ControlCallCmd::StartFrameFps(v);
} else if (v[typeName] == "fpsohtest") {
@ -68,6 +67,8 @@ std::string ControlCallCmd::GetResult(std::vector<std::string> v)
result = ControlCallCmd::GetAppStartTime();
} else if (v[typeName] == "slideList") {
result = ControlCallCmd::SlideList();
} else if (v[typeName] == "timmeDelay") {
result = ControlCallCmd::TimeDelay();
}
if (time == noNameType) {
std::cout << "Startup error, unknown application or application not responding" << std::endl;
@ -80,6 +81,33 @@ std::string ControlCallCmd::GetResult(std::vector<std::string> v)
}
return result;
}
std::string ControlCallCmd::TimeDelay()
{
OHOS::SmartPerf::ParseClickResponseTrace pcrt;
OHOS::SmartPerf::StartUpDelay sd;
std::string cmdResult;
OHOS::SmartPerf::Radar radar;
SPUtils::LoadCmd("rm -rfv /data/local/tmp/sp_trace_delay.ftrace", cmdResult);
std::string traceName = std::string("/data/local/tmp/") + std::string("sp_trace_") + "delay" + ".ftrace";
std::thread thGetTrace = sd.ThreadGetTrace("delay", traceName);
std::thread thGetHisysId = sd.ThreadGetHisysIdResponse();
std::thread thGetHisysId2 = sd.ThreadGetHisysIdComplete();
std::future<std::string> futureResult = std::async(std::launch::async, SPUtils::GetRadarResponse);
std::future<std::string> futureResult2 = std::async(std::launch::async, SPUtils::GetRadarComplete);
std::string str = futureResult.get();
std::string str2 = futureResult2.get();
thGetTrace.join();
thGetHisysId.join();
thGetHisysId2.join();
double strResponseTime = radar.ParseRadarResponse(str);
stream << strResponseTime;
double strCompleteTime = radar.ParseRadarResponse(str2);
std::ostringstream streamComplete;
streamComplete << strCompleteTime;
std::string resultTime = "ResponseTime:" + stream.str() + "ms\n" +
"CompleteTime:" + streamComplete.str() + "ms";
return resultTime;
}
std::string ControlCallCmd::SlideList()
{
OHOS::SmartPerf::ParseClickResponseTrace pcrt;
@ -152,35 +180,6 @@ std::string ControlCallCmd::SlideFps(std::vector<std::string> v)
std::string fps = parseFPS.ParseTraceFile(traceName, v[typePKG]);
return fps;
}
std::string ControlCallCmd::SlideFPS(std::vector<std::string> v)
{
OHOS::SmartPerf::StartUpDelay sd;
ParseFPS parseFPS;
std::string cmdResult;
int type = 4;
int typePKG = 3;
SPUtils::LoadCmd("rm -rfv /data/local/tmp/*.json", cmdResult);
SPUtils::LoadCmd("rm -rfv /data/local/tmp/*.ftrace", cmdResult);
SPUtils::LoadCmd("uitest dumpLayout", cmdResult);
sleep(1);
size_t position = cmdResult.find(":");
size_t position2 = cmdResult.find("json");
std::string pathJson = cmdResult.substr(position + 1, position2 - position + typePKG);
std::string deviceType = sd.GetDeviceType();
sd.InitXY2(v[type], pathJson, v[typePKG]);
std::string traceName = std::string("/data/local/tmp/") + std::string("sp_trace_") + "fps" + ".ftrace";
std::string cmd = "uinput -T -d " + sd.pointXY + " -u " + sd.pointXY;
sleep(1);
SPUtils::LoadCmd(cmd, cmdResult);
sleep(1);
std::thread thGetTrace = sd.ThreadGetTrace("fps", traceName);
sleep(1);
cmd = "uinput -T -m 650 1500 650 500 30";
SPUtils::LoadCmd(cmd, cmdResult);
thGetTrace.join();
std::string fps = parseFPS.ParseTraceFile(traceName, v[typePKG]);
return fps;
}
double ControlCallCmd::ResponseTime()
{
OHOS::SmartPerf::ParseClickResponseTrace pcrt;

View File

@ -26,12 +26,21 @@ public:
static Network instance;
return instance;
}
std::map<std::string, std::string> GetNetworkInfo() const;
std::map<std::string, std::string> GetNetworkInfo();
private:
Network() {};
Network(const Network &);
Network &operator = (const Network &);
long long allTx = 0;
long long allRx = 0;
long long curTx = 0;
long long curRx = 0;
long long diffTx = 0;
long long diffRx = 0;
long long prevTx = 0;
long long prevRx = 0;
bool isFirst = true;
};
}
}

View File

@ -28,7 +28,6 @@ public:
double CompleteTime();
double ResponseTime();
double StartResponse(std::vector<std::string> v);
static std::string SlideFPS(std::vector<std::string> v);
static std::string SlideFps(std::vector<std::string> v);
double PageFps();
std::string StartFrameFps(std::vector<std::string> v);
@ -36,6 +35,7 @@ public:
std::string GetFrame();
std::string GetAppStartTime();
std::string SlideList();
std::string TimeDelay();
private:
bool isOhTest = false;
std::string result = "";

View File

@ -30,11 +30,11 @@ public:
const std::string smartPerfMsg = "usage: SP_daemon <options> <arguments> \n"
"--------------------------------------------------------------------\n"
"These are common commands list:\n"
" -N set num of profiler <must be non-null>\n"
" -PKG set pkgname of profiler \n"
" -c get device cpuFreq、cpuUsage and process cpuUsage、cpuLoad .. \n"
" -g get gpuFreq and gpuLoad \n"
" -f get fps and fps jitters \n"
" -N set the collection times, for example: -N 10 \n"
" -PKG set package name, must add, for example: -PKG ohos.samples.ecg \n"
" -c get device cpuFreq and cpuUsage, process cpuUsage and cpuLoad .. \n"
" -g get device gpuFreq and gpuLoad \n"
" -f get app refresh fps and fps jitters \n"
" -t get soc-temp gpu-temp .. \n"
" -p get current_now and voltage_now \n"
" -r get process memory and total memory .. \n"

View File

@ -25,6 +25,10 @@ public:
std::thread ThreadGetLayout();
void InputEvent(const std::string &point);
std::thread ThreadInputEvent(const std::string &point);
void GetHisysIdResponse();
std::thread ThreadGetHisysIdResponse();
void GetHisysIdComplete();
std::thread ThreadGetHisysIdComplete();
void GetHisysId();
std::thread ThreadGetHisysId();
void ChangeToBackground();

View File

@ -76,19 +76,65 @@ void StartUpDelay::GetHisysId()
std::stringstream ss(str);
std::string line = "";
getline(ss, line);
std::stringstream ss_line(line);
std::stringstream ssLine(line);
std::string word = "";
std::string second_str;
std::string secondStr;
int count = 0;
int num = 2;
while (ss_line >> word) {
while (ssLine >> word) {
count++;
if (count == num) {
second_str = word;
secondStr = word;
break;
}
}
SPUtils::LoadCmd("kill " + second_str, str);
SPUtils::LoadCmd("kill " + secondStr, str);
}
void StartUpDelay::GetHisysIdResponse()
{
int time = 10;
sleep(time);
std::string str = "";
SPUtils::LoadCmd("ps -ef |grep INTERACTION_RESPONSE_LATENCY", str);
std::stringstream ss(str);
std::string line = "";
getline(ss, line);
std::stringstream ssLine(line);
std::string word = "";
std::string secondStr;
int count = 0;
int num = 2;
while (ssLine >> word) {
count++;
if (count == num) {
secondStr = word;
break;
}
}
SPUtils::LoadCmd("kill " + secondStr, str);
}
void StartUpDelay::GetHisysIdComplete()
{
int time = 10;
sleep(time);
std::string str = "";
SPUtils::LoadCmd("ps -ef |grep INTERACTION_COMPLETED_LATENCY", str);
std::stringstream ss(str);
std::string line = "";
getline(ss, line);
std::stringstream ssLine(line);
std::string word = "";
std::string secondStr;
int count = 0;
int num = 2;
while (ssLine >> word) {
count++;
if (count == num) {
secondStr = word;
break;
}
}
SPUtils::LoadCmd("kill " + secondStr, str);
}
bool StartUpDelay::GetSpTcp()
{
@ -103,11 +149,21 @@ bool StartUpDelay::GetSpTcp()
}
return flagTcp;
}
std::thread StartUpDelay::ThreadGetHisysIdResponse()
{
std::thread thGetHisysIdResponse(&StartUpDelay::GetHisysIdResponse, this);
return thGetHisysIdResponse;
}
std::thread StartUpDelay::ThreadGetHisysId()
{
std::thread thGetHisysId(&StartUpDelay::GetHisysId, this);
return thGetHisysId;
}
std::thread StartUpDelay::ThreadGetHisysIdComplete()
{
std::thread thGetHisysIdComplete(&StartUpDelay::GetHisysIdComplete, this);
return thGetHisysIdComplete;
}
void StartUpDelay::ChangeToBackground()
{
std::string result;