mirror of
https://gitee.com/openharmony/developtools_hiperf
synced 2024-11-27 09:40:42 +00:00
hmperf: Add server pid
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
This commit is contained in:
parent
8cc7cfd3f0
commit
4d61d1b86d
@ -239,6 +239,7 @@ public:
|
||||
// used for data_.ips replace (ReplaceWithCallStack)
|
||||
std::vector<u64> ips_;
|
||||
std::vector<CallFrame> callFrames_;
|
||||
std::vector<pid_t> serverPidMap_;
|
||||
|
||||
// referenced input(p) in PerfRecordSample, require caller keep input(p) together
|
||||
PerfRecordSample(uint8_t *p, const perf_event_attr &attr);
|
||||
@ -261,6 +262,8 @@ public:
|
||||
data_.id = 0;
|
||||
header.size = sizeof(header) + sizeof(data_);
|
||||
};
|
||||
|
||||
pid_t GetServerPidof(unsigned int ip_nr);
|
||||
};
|
||||
|
||||
class PerfRecordExit : public PerfEventRecord {
|
||||
|
@ -26,6 +26,7 @@ namespace HiPerf {
|
||||
// description from https://man7.org/linux/man-pages/man2/perf_event_open.2.html
|
||||
|
||||
#define SAMPLE_ID_ALL 0
|
||||
#define PERF_SAMPLE_SERVER_PID (1U << 31)
|
||||
|
||||
struct sample_id {
|
||||
u32 pid;
|
||||
@ -171,6 +172,8 @@ struct PerfRecordSampleData {
|
||||
u64 intr_regs[0]; /* if PERF_SAMPLE_REGS_INTR */
|
||||
u64 phys_addr; /* if PERF_SAMPLE_PHYS_ADDR */
|
||||
u64 cgroup; /* if PERF_SAMPLE_CGROUP */
|
||||
u64 server_nr; /* if PERF_SAMPLE_SERVER_PID */
|
||||
u64 *server_pids; /* if PERF_SAMPLE_SERVER_PID */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -177,7 +177,7 @@ private:
|
||||
std::unordered_set<uint64_t> missedRuntimeVaddr_;
|
||||
#endif
|
||||
void SymbolicCallFrame(PerfRecordSample &recordSample, uint64_t ip,
|
||||
perf_callchain_context context);
|
||||
pid_t server_pid, perf_callchain_context context);
|
||||
|
||||
std::vector<std::string> symbolsPaths_;
|
||||
|
||||
|
@ -282,6 +282,11 @@ PerfRecordSample::PerfRecordSample(uint8_t *p, const perf_event_attr &attr)
|
||||
data_.user_regs = reinterpret_cast<u64 *>(p);
|
||||
p += data_.reg_nr * sizeof(u64);
|
||||
}
|
||||
PopFromBinary(sampleType_ & PERF_SAMPLE_SERVER_PID, p, data_.server_nr);
|
||||
if (data_.server_nr > 0) {
|
||||
data_.server_pids = reinterpret_cast<u64 *>(p);
|
||||
p += data_.server_nr * sizeof(u64);
|
||||
}
|
||||
PopFromBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size);
|
||||
if (data_.stack_size > 0) {
|
||||
data_.stack_data = p;
|
||||
@ -328,6 +333,11 @@ bool PerfRecordSample::GetBinary(std::vector<uint8_t> &buf) const
|
||||
std::copy(data_.user_regs, data_.user_regs + data_.reg_nr, reinterpret_cast<u64 *>(p));
|
||||
p += data_.reg_nr * sizeof(u64);
|
||||
}
|
||||
PushToBinary(sampleType_ & PERF_SAMPLE_SERVER_PID, p, data_.server_nr);
|
||||
if (data_.server_nr > 0) {
|
||||
std::copy(data_.server_pids, data_.server_pids + data_.server_nr, reinterpret_cast<u64 *>(p));
|
||||
p += data_.server_nr * sizeof(u64);
|
||||
}
|
||||
PushToBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size);
|
||||
if (data_.stack_size > 0) {
|
||||
std::copy(data_.stack_data, data_.stack_data + data_.stack_size, p);
|
||||
@ -408,6 +418,12 @@ void PerfRecordSample::DumpData(int indent) const
|
||||
PrintIndent(indent + 1, "0x%llx\n", data_.user_regs[i]);
|
||||
}
|
||||
}
|
||||
if (sampleType_ & PERF_SAMPLE_SERVER_PID) {
|
||||
PrintIndent(indent, "server nr=%lld\n", data_.server_nr);
|
||||
for (uint64_t i = 0; i < data_.server_nr; ++i) {
|
||||
PrintIndent(indent + 1, "pid: %llu\n", data_.server_pids[i]);
|
||||
}
|
||||
}
|
||||
if (sampleType_ & PERF_SAMPLE_STACK_USER) {
|
||||
PrintIndent(indent, "user stack: size %llu dyn_size %lld\n", data_.stack_size,
|
||||
data_.dyn_size);
|
||||
@ -897,6 +913,48 @@ void PerfRecordSwitchCpuWide::DumpData(int indent) const
|
||||
PrintIndent(indent, "next_prev_pid %u, next_prev_tid %u\n", data_.next_prev_pid,
|
||||
data_.next_prev_tid);
|
||||
}
|
||||
|
||||
pid_t PerfRecordSample::GetServerPidof(unsigned int ip_nr)
|
||||
{
|
||||
if (!data_.server_nr) {
|
||||
return data_.pid;
|
||||
}
|
||||
|
||||
// init serverPidMap_
|
||||
if (!serverPidMap_.size()) {
|
||||
size_t curr_server = 0;
|
||||
// ip_nr == 0: server_pid of data_.ip
|
||||
serverPidMap_.emplace_back(data_.server_pids[curr_server]);
|
||||
// ip_nr == 1...nr: server_pid of data_.ips[nr]
|
||||
for (size_t i = 1; i < data_.nr; i++) {
|
||||
// context change, use next server pid
|
||||
if (data_.ips[i] >= PERF_CONTEXT_MAX) {
|
||||
curr_server++;
|
||||
}
|
||||
if (curr_server >= data_.server_nr) {
|
||||
HLOGE("callchain server pid nr %zu out of range", curr_server);
|
||||
break;
|
||||
}
|
||||
serverPidMap_.emplace_back(data_.server_pids[curr_server]);
|
||||
}
|
||||
// ip_nr == nr + 1: server_pid of ustack
|
||||
curr_server++;
|
||||
if (data_.stack_size) {
|
||||
if (curr_server >= data_.server_nr) {
|
||||
HLOGE("ustack server pid nr %zu out of range", curr_server);
|
||||
} else {
|
||||
serverPidMap_.emplace_back(data_.server_pids[curr_server]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return server pid
|
||||
if (ip_nr >= serverPidMap_.size()) {
|
||||
return data_.pid;
|
||||
} else {
|
||||
return serverPidMap_[ip_nr];
|
||||
}
|
||||
}
|
||||
} // namespace HiPerf
|
||||
} // namespace Developtools
|
||||
} // namespace OHOS
|
||||
|
@ -354,6 +354,10 @@ bool PerfEvents::AddEvent(perf_type_id type, __u64 config, bool excludeUser, boo
|
||||
} else {
|
||||
eventItem.attr.sample_type = SAMPLE_TYPE;
|
||||
}
|
||||
|
||||
if (isHM_) {
|
||||
eventItem.attr.sample_type |= PERF_SAMPLE_SERVER_PID;
|
||||
}
|
||||
}
|
||||
|
||||
// set clock id
|
||||
@ -1287,6 +1291,11 @@ size_t PerfEvents::GetStackSizePosInSampleRecord(MmapFd &mmap)
|
||||
pos += reg_nr * sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
if (mmap.attr->sample_type & PERF_SAMPLE_SERVER_PID) {
|
||||
uint64_t server_nr = 0;
|
||||
GetRecordFieldFromMmap(mmap, &server_nr, mmap.mmapPage->data_tail + pos, sizeof(server_nr));
|
||||
pos += (sizeof(server_nr) + server_nr * sizeof(uint64_t));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -297,6 +297,7 @@ static std::map<int, std::string> g_sampleTypeNames = {
|
||||
{PERF_SAMPLE_IDENTIFIER, "identifier"},
|
||||
{PERF_SAMPLE_TRANSACTION, "transaction"},
|
||||
{PERF_SAMPLE_REGS_INTR, "reg_intr"},
|
||||
{PERF_SAMPLE_SERVER_PID, "server_pid"},
|
||||
};
|
||||
|
||||
void SubCommandDump::DumpSampleType(uint64_t sampleType, int indent)
|
||||
|
@ -1491,14 +1491,16 @@ bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
||||
#if USE_COLLECT_SYMBOLIC
|
||||
perf_callchain_context context = record->inKernel() ? PERF_CONTEXT_KERNEL
|
||||
: PERF_CONTEXT_USER;
|
||||
pid_t server_pid;
|
||||
// if no nr use ip
|
||||
if (sample->data_.nr == 0) {
|
||||
if (virtualRuntime_.IsKernelThread(sample->data_.pid)) {
|
||||
kernelThreadSymbolsHits_[sample->data_.pid].insert(sample->data_.ip);
|
||||
server_pid = sample->GetServerPidof(0);
|
||||
if (virtualRuntime_.IsKernelThread(server_pid)) {
|
||||
kernelThreadSymbolsHits_[server_pid].insert(sample->data_.ip);
|
||||
} else if (context == PERF_CONTEXT_KERNEL) {
|
||||
kernelSymbolsHits_.insert(sample->data_.ip);
|
||||
} else {
|
||||
userSymbolsHits_[sample->data_.pid].insert(sample->data_.ip);
|
||||
userSymbolsHits_[server_pid].insert(sample->data_.ip);
|
||||
}
|
||||
} else {
|
||||
for (u64 i = 0; i < sample->data_.nr; i++) {
|
||||
@ -1509,12 +1511,13 @@ bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
||||
context = PERF_CONTEXT_USER;
|
||||
}
|
||||
} else {
|
||||
if (virtualRuntime_.IsKernelThread(sample->data_.pid)) {
|
||||
kernelThreadSymbolsHits_[sample->data_.pid].insert(sample->data_.ips[i]);
|
||||
server_pid = sample->GetServerPidof(i);
|
||||
if (virtualRuntime_.IsKernelThread(server_pid)) {
|
||||
kernelThreadSymbolsHits_[server_pid].insert(sample->data_.ips[i]);
|
||||
} else if (context == PERF_CONTEXT_KERNEL) {
|
||||
kernelSymbolsHits_.insert(sample->data_.ips[i]);
|
||||
} else {
|
||||
userSymbolsHits_[sample->data_.pid].insert(sample->data_.ips[i]);
|
||||
userSymbolsHits_[server_pid].insert(sample->data_.ips[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,9 +316,14 @@ void VirtualRuntime::MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame)
|
||||
}
|
||||
|
||||
void VirtualRuntime::SymbolicCallFrame(PerfRecordSample &recordSample, uint64_t ip,
|
||||
perf_callchain_context context)
|
||||
pid_t server_pid, perf_callchain_context context)
|
||||
{
|
||||
auto symbol = GetSymbol(ip, recordSample.data_.pid, recordSample.data_.tid, context);
|
||||
pid_t pid = recordSample.data_.pid;
|
||||
pid_t tid = recordSample.data_.tid;
|
||||
if (server_pid != pid) {
|
||||
pid = tid = server_pid;
|
||||
}
|
||||
auto symbol = GetSymbol(ip, pid, tid, context);
|
||||
MakeCallFrame(symbol, recordSample.callFrames_.emplace_back(ip, 0));
|
||||
HLOGV(" (%zu)unwind symbol: %*s%s", recordSample.callFrames_.size(),
|
||||
static_cast<int>(recordSample.callFrames_.size()), "",
|
||||
@ -333,8 +338,10 @@ void VirtualRuntime::SymbolicRecord(PerfRecordSample &recordSample)
|
||||
// Symbolic the Call Stack
|
||||
recordSample.callFrames_.clear();
|
||||
perf_callchain_context context = PERF_CONTEXT_MAX;
|
||||
pid_t server_pid;
|
||||
if (recordSample.data_.nr == 0) {
|
||||
SymbolicCallFrame(recordSample, recordSample.data_.ip, PERF_CONTEXT_MAX);
|
||||
server_pid = recordSample.GetServerPidof(0);
|
||||
SymbolicCallFrame(recordSample, recordSample.data_.ip, server_pid, PERF_CONTEXT_MAX);
|
||||
}
|
||||
for (u64 i = 0; i < recordSample.data_.nr; i++) {
|
||||
uint64_t ip = recordSample.data_.ips[i];
|
||||
@ -346,7 +353,8 @@ void VirtualRuntime::SymbolicRecord(PerfRecordSample &recordSample)
|
||||
// ip 0 or 1 or less than 0
|
||||
continue;
|
||||
}
|
||||
SymbolicCallFrame(recordSample, ip, context);
|
||||
server_pid = recordSample.GetServerPidof(i);
|
||||
SymbolicCallFrame(recordSample, ip, server_pid, context);
|
||||
}
|
||||
#ifdef HIPERF_DEBUG_TIME
|
||||
auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime);
|
||||
@ -366,7 +374,13 @@ void VirtualRuntime::UnwindFromRecord(PerfRecordSample &recordSample)
|
||||
HLOGV("unwind record (time:%llu)", recordSample.data_.time);
|
||||
// if we have userstack ?
|
||||
if (recordSample.data_.stack_size > 0) {
|
||||
auto &thread = UpdateThread(recordSample.data_.pid, recordSample.data_.tid);
|
||||
pid_t server_pid = recordSample.GetServerPidof(recordSample.data_.nr + 1);
|
||||
pid_t pid = recordSample.data_.pid;
|
||||
pid_t tid = recordSample.data_.tid;
|
||||
if (server_pid != pid) {
|
||||
pid = tid = server_pid;
|
||||
}
|
||||
auto &thread = UpdateThread(pid, tid);
|
||||
callstack_.UnwindCallStack(thread, recordSample.data_.user_abi == PERF_SAMPLE_REGS_ABI_32,
|
||||
recordSample.data_.user_regs, recordSample.data_.reg_nr,
|
||||
recordSample.data_.stack_data, recordSample.data_.dyn_size,
|
||||
@ -381,6 +395,8 @@ void VirtualRuntime::UnwindFromRecord(PerfRecordSample &recordSample)
|
||||
recordSample.callFrames_.size() - oldSize);
|
||||
|
||||
recordSample.ReplaceWithCallStack(oldSize);
|
||||
// callchain updated, flush server pid map
|
||||
recordSample.serverPidMap_.clear();
|
||||
}
|
||||
|
||||
#ifdef HIPERF_DEBUG_TIME
|
||||
@ -398,6 +414,13 @@ void VirtualRuntime::UnwindFromRecord(PerfRecordSample &recordSample)
|
||||
void VirtualRuntime::UpdateFromRecord(PerfRecordSample &recordSample)
|
||||
{
|
||||
UpdateThread(recordSample.data_.pid, recordSample.data_.tid);
|
||||
if (recordSample.data_.server_nr) {
|
||||
// update all server threads
|
||||
for (size_t i = 0; i < recordSample.data_.server_nr; i++) {
|
||||
pid_t pid = recordSample.data_.server_pids[i];
|
||||
UpdateThread(pid, pid);
|
||||
}
|
||||
}
|
||||
// unwind
|
||||
if (disableUnwind_) {
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user