mirror of
https://gitee.com/openharmony/developtools_hiperf
synced 2024-11-23 07:29:42 +00:00
commit
3d84e3f263
@ -23,6 +23,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unique_fd.h>
|
#include <unique_fd.h>
|
||||||
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
@ -39,63 +40,34 @@ namespace OHOS {
|
|||||||
namespace Developtools {
|
namespace Developtools {
|
||||||
namespace HiPerf {
|
namespace HiPerf {
|
||||||
using namespace OHOS::HiviewDFX;
|
using namespace OHOS::HiviewDFX;
|
||||||
|
using PerfRecordType = int32_t;
|
||||||
|
|
||||||
static constexpr uint32_t RECORD_SIZE_LIMIT = 65535;
|
static constexpr uint32_t RECORD_SIZE_LIMIT = 65535;
|
||||||
static constexpr uint32_t RECORD_SIZE_LIMIT_SPE = 524288; // auxMmapPages_ * pageSize_
|
static constexpr uint32_t RECORD_SIZE_LIMIT_SPE = 524288; // auxMmapPages_ * pageSize_
|
||||||
|
|
||||||
|
static constexpr char PERF_RECORD_TYPE_AUXTRACE[] = "auxtrace";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_SAMPLE[] = "sample";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_MMAP[] = "mmap";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_MMAP2[] = "mmap2";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_LOST[] = "lost";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_COMM[] = "comm";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_EXIT[] = "exit";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_THROTTLE[] = "throttle";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_UNTHROTTLE[] = "unthrottle";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_FORK[] = "fork";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_READ[] = "read";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_AUX[] = "aux";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_ITRACESTART[] = "itraceStart";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_LOSTSAMPLE[] = "lostSamples";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_SWITCH[] = "switch";
|
||||||
|
static constexpr char PERF_RECORD_TYPE_SWITCHCPUWIDE[] = "switchCpuWide";
|
||||||
|
static constexpr char* PERF_RECORD_TYPE_NULL = nullptr;
|
||||||
|
|
||||||
enum perf_event_hiperf_ext_type {
|
enum perf_event_hiperf_ext_type {
|
||||||
PERF_RECORD_AUXTRACE = 71,
|
PERF_RECORD_AUXTRACE = 71,
|
||||||
PERF_RECORD_HIPERF_CALLSTACK = UINT32_MAX / 2,
|
PERF_RECORD_HIPERF_CALLSTACK = UINT32_MAX / 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallFrame {
|
|
||||||
uint64_t ip_ = 0; // pc
|
|
||||||
uint64_t sp_ = 0; // sp
|
|
||||||
int32_t symbolFileIndex_ = -1; // symbolFileIndex_, symbols file index, used to report protobuf file
|
|
||||||
uint64_t vaddrInFile_ = 0; // funcOffset, vaddr of symbol in file
|
|
||||||
uint64_t offsetToVaddr_ = 0; // mapOffset, offset of ip to vaddr
|
|
||||||
int32_t symbolIndex_ = -1; // index, symbols index , should update after sort
|
|
||||||
std::string_view symbolName_; // funcName
|
|
||||||
std::string_view filePath_; // mapName, lib path , elf path
|
|
||||||
|
|
||||||
CallFrame(uint64_t ip, uint64_t sp = 0) : ip_(ip), sp_(sp) {}
|
|
||||||
|
|
||||||
// this is for ut test
|
|
||||||
CallFrame(uint64_t ip, uint64_t vaddrInFile, const char *name, const char *filePath)
|
|
||||||
: ip_(ip), vaddrInFile_(vaddrInFile), symbolName_(name), filePath_(filePath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
bool operator==(const CallFrame &b) const
|
|
||||||
{
|
|
||||||
return (ip_ == b.ip_) && (sp_ == b.sp_);
|
|
||||||
}
|
|
||||||
bool operator!=(const CallFrame &b) const
|
|
||||||
{
|
|
||||||
return (ip_ != b.ip_) || (sp_ != b.sp_);
|
|
||||||
}
|
|
||||||
std::string ToString() const
|
|
||||||
{
|
|
||||||
return StringPrintf("ip: 0x%016llx sp: 0x%016llx", ip_, sp_);
|
|
||||||
}
|
|
||||||
std::string ToSymbolString() const
|
|
||||||
{
|
|
||||||
std::string output = StringPrintf(" 0x%016llx : ", ip_);
|
|
||||||
output.append(symbolName_);
|
|
||||||
if (vaddrInFile_ != 0) {
|
|
||||||
output += StringPrintf("[0x%016llx:0x%016llx][+0x%llx]", ip_ - offsetToVaddr_,
|
|
||||||
vaddrInFile_, offsetToVaddr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.append("@");
|
|
||||||
output.append(filePath_);
|
|
||||||
if (symbolIndex_ != -1) {
|
|
||||||
output.append(":");
|
|
||||||
output.append(std::to_string(symbolIndex_));
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AttrWithId {
|
struct AttrWithId {
|
||||||
perf_event_attr attr;
|
perf_event_attr attr;
|
||||||
std::vector<uint64_t> ids;
|
std::vector<uint64_t> ids;
|
||||||
@ -104,50 +76,39 @@ struct AttrWithId {
|
|||||||
|
|
||||||
class PerfEventRecord {
|
class PerfEventRecord {
|
||||||
public:
|
public:
|
||||||
PerfEventRecord(const PerfEventRecord &) = delete;
|
struct perf_event_header header_ = {};
|
||||||
PerfEventRecord &operator=(const PerfEventRecord &) = delete;
|
|
||||||
|
|
||||||
struct perf_event_header header;
|
virtual const char* GetName() const = 0;
|
||||||
const std::string name_ {};
|
virtual void Init(uint8_t* data, const perf_event_attr& attr) = 0;
|
||||||
|
|
||||||
PerfEventRecord(perf_event_type type, bool inKernel, const std::string &name);
|
virtual ~PerfEventRecord() = default;
|
||||||
PerfEventRecord(perf_event_hiperf_ext_type type, const std::string &name);
|
|
||||||
|
|
||||||
PerfEventRecord(uint8_t *p, const std::string &name);
|
|
||||||
|
|
||||||
virtual ~PerfEventRecord() {}
|
|
||||||
|
|
||||||
virtual size_t GetSize() const
|
virtual size_t GetSize() const
|
||||||
{
|
{
|
||||||
return header.size;
|
return header_.size;
|
||||||
};
|
};
|
||||||
size_t GetHeaderSize() const
|
size_t GetHeaderSize() const
|
||||||
{
|
{
|
||||||
return sizeof(header);
|
return sizeof(header_);
|
||||||
};
|
};
|
||||||
void GetHeaderBinary(std::vector<uint8_t> &buf) const;
|
void GetHeaderBinary(std::vector<uint8_t> &buf) const;
|
||||||
|
|
||||||
uint32_t GetType() const
|
uint32_t GetType() const
|
||||||
{
|
{
|
||||||
return header.type;
|
return header_.type;
|
||||||
};
|
};
|
||||||
uint16_t GetMisc() const
|
uint16_t GetMisc() const
|
||||||
{
|
{
|
||||||
return header.misc;
|
return header_.misc;
|
||||||
};
|
};
|
||||||
bool inKernel()
|
bool InKernel()
|
||||||
{
|
{
|
||||||
return header.misc & PERF_RECORD_MISC_KERNEL;
|
return header_.misc & PERF_RECORD_MISC_KERNEL;
|
||||||
}
|
}
|
||||||
bool inUser()
|
bool InUser()
|
||||||
{
|
{
|
||||||
return header.misc & PERF_RECORD_MISC_USER;
|
return header_.misc & PERF_RECORD_MISC_USER;
|
||||||
}
|
}
|
||||||
const std::string &GetName() const
|
|
||||||
{
|
|
||||||
return name_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// to support --exclude-hiperf, return sample_id.pid to filter record,
|
// to support --exclude-hiperf, return sample_id.pid to filter record,
|
||||||
virtual pid_t GetPid() const
|
virtual pid_t GetPid() const
|
||||||
{
|
{
|
||||||
@ -157,7 +118,42 @@ public:
|
|||||||
virtual bool GetBinary(std::vector<uint8_t> &buf) const = 0;
|
virtual bool GetBinary(std::vector<uint8_t> &buf) const = 0;
|
||||||
void Dump(int indent = 0, std::string outputFilename = "", FILE *outputDump = nullptr) const;
|
void Dump(int indent = 0, std::string outputFilename = "", FILE *outputDump = nullptr) const;
|
||||||
virtual void DumpData(int indent) const = 0;
|
virtual void DumpData(int indent) const = 0;
|
||||||
virtual void DumpLog(const std::string &prefix) const;
|
virtual void DumpLog(const std::string& prefix) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Init(perf_event_type type, bool inKernel);
|
||||||
|
void Init(perf_event_hiperf_ext_type type);
|
||||||
|
void InitHeader(uint8_t* p);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DataType, const char* RECORD_TYPE_NAME>
|
||||||
|
class PerfEventRecordTemplate : public PerfEventRecord {
|
||||||
|
public:
|
||||||
|
PerfEventRecordTemplate(const PerfEventRecordTemplate&) = delete;
|
||||||
|
PerfEventRecordTemplate& operator=(const PerfEventRecordTemplate&) = delete;
|
||||||
|
|
||||||
|
DataType data_ = {};
|
||||||
|
const char* GetName() const override final
|
||||||
|
{
|
||||||
|
return RECORD_TYPE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
PerfEventRecordTemplate() = default;
|
||||||
|
virtual ~PerfEventRecordTemplate() = default;
|
||||||
|
void Init(uint8_t* p, const perf_event_attr& = {}) override
|
||||||
|
{
|
||||||
|
InitHeader(p);
|
||||||
|
|
||||||
|
size_t dataSize = GetSize();
|
||||||
|
if (dataSize >= sizeof(header_)) {
|
||||||
|
size_t copySize = dataSize - sizeof(header_);
|
||||||
|
if (memcpy_s(reinterpret_cast<uint8_t*>(&data_), sizeof(data_), p + sizeof(header_), copySize) != 0) {
|
||||||
|
HLOGE("init perf record memcpy_s failed!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HLOGE("init perf record failed!");
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// define convert from linux/perf_event.h
|
// define convert from linux/perf_event.h
|
||||||
@ -171,12 +167,12 @@ constexpr __u64 SAMPLE_TYPE = PERF_SAMPLE_IP | SAMPLE_ID | PERF_SAMPLE_PERIOD;
|
|||||||
constexpr __u32 MIN_SAMPLE_STACK_SIZE = 8;
|
constexpr __u32 MIN_SAMPLE_STACK_SIZE = 8;
|
||||||
constexpr __u32 MAX_SAMPLE_STACK_SIZE = 65528;
|
constexpr __u32 MAX_SAMPLE_STACK_SIZE = 65528;
|
||||||
|
|
||||||
class PerfRecordAuxtrace : public PerfEventRecord {
|
class PerfRecordAuxtrace : public PerfEventRecordTemplate<PerfRecordAuxtraceData, PERF_RECORD_TYPE_AUXTRACE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordAuxtraceData data_;
|
|
||||||
u8* rawData_ = nullptr;
|
u8* rawData_ = nullptr;
|
||||||
explicit PerfRecordAuxtrace(uint8_t *p);
|
PerfRecordAuxtrace() = default;
|
||||||
PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32 idx, u32 tid, u32 cpu, u32 pid);
|
PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32 idx, u32 tid, u32 cpu, u32 pid);
|
||||||
|
void Init(uint8_t* data, const perf_event_attr& attr) override;
|
||||||
|
|
||||||
bool GetBinary1(std::vector<uint8_t> &buf) const;
|
bool GetBinary1(std::vector<uint8_t> &buf) const;
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
@ -186,12 +182,9 @@ public:
|
|||||||
virtual size_t GetSize() const override;
|
virtual size_t GetSize() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordMmap : public PerfEventRecord {
|
class PerfRecordMmap : public PerfEventRecordTemplate<PerfRecordMmapData, PERF_RECORD_TYPE_MMAP> {
|
||||||
public:
|
public:
|
||||||
PerfRecordMmapData data_;
|
PerfRecordMmap() = default;
|
||||||
|
|
||||||
explicit PerfRecordMmap(uint8_t *p);
|
|
||||||
|
|
||||||
PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
||||||
const std::string &filename);
|
const std::string &filename);
|
||||||
|
|
||||||
@ -200,11 +193,10 @@ public:
|
|||||||
void DumpLog(const std::string &prefix) const override;
|
void DumpLog(const std::string &prefix) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordMmap2 : public PerfEventRecord {
|
class PerfRecordMmap2 : public PerfEventRecordTemplate<PerfRecordMmap2Data, PERF_RECORD_TYPE_MMAP2> {
|
||||||
public:
|
public:
|
||||||
PerfRecordMmap2Data data_;
|
|
||||||
|
|
||||||
explicit PerfRecordMmap2(uint8_t *p);
|
PerfRecordMmap2() = default;
|
||||||
|
|
||||||
PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, u32 maj, u32 min,
|
PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, u32 maj, u32 min,
|
||||||
u64 ino, u32 prot, u32 flags, const std::string &filename);
|
u64 ino, u32 prot, u32 flags, const std::string &filename);
|
||||||
@ -217,31 +209,28 @@ public:
|
|||||||
bool discard_ = false;
|
bool discard_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordLost : public PerfEventRecord {
|
class PerfRecordLost : public PerfEventRecordTemplate<PerfRecordLostData, PERF_RECORD_TYPE_LOST> {
|
||||||
public:
|
public:
|
||||||
PerfRecordLostData data_;
|
|
||||||
|
|
||||||
explicit PerfRecordLost(uint8_t *p);
|
PerfRecordLost() = default;
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
|
|
||||||
// only for UT
|
// only for UT
|
||||||
PerfRecordLost(bool inKernel, u64 id, u64 lost)
|
PerfRecordLost(bool inKernel, u64 id, u64 lost)
|
||||||
: PerfEventRecord(PERF_RECORD_LOST, inKernel, "lost")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_LOST, inKernel);
|
||||||
data_.id = id;
|
data_.id = id;
|
||||||
data_.lost = lost;
|
data_.lost = lost;
|
||||||
header.size = sizeof(header) + sizeof(data_);
|
header_.size = sizeof(header_) + sizeof(data_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordComm : public PerfEventRecord {
|
class PerfRecordComm : public PerfEventRecordTemplate<PerfRecordCommData, PERF_RECORD_TYPE_COMM> {
|
||||||
public:
|
public:
|
||||||
PerfRecordCommData data_;
|
|
||||||
|
|
||||||
explicit PerfRecordComm(uint8_t *p);
|
|
||||||
|
|
||||||
|
PerfRecordComm() = default;
|
||||||
PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm);
|
PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm);
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
@ -249,9 +238,8 @@ public:
|
|||||||
void DumpLog(const std::string &prefix) const override;
|
void DumpLog(const std::string &prefix) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordSample : public PerfEventRecord {
|
class PerfRecordSample : public PerfEventRecordTemplate<PerfRecordSampleData, PERF_RECORD_TYPE_SAMPLE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordSampleData data_ = {};
|
|
||||||
uint64_t sampleType_ = SAMPLE_TYPE;
|
uint64_t sampleType_ = SAMPLE_TYPE;
|
||||||
uint64_t skipKernel_ = 0;
|
uint64_t skipKernel_ = 0;
|
||||||
uint64_t skipPid_ = 0;
|
uint64_t skipPid_ = 0;
|
||||||
@ -262,11 +250,15 @@ public:
|
|||||||
static std::vector<DfxFrame> callFrames_;
|
static std::vector<DfxFrame> callFrames_;
|
||||||
static std::vector<pid_t> serverPidMap_;
|
static std::vector<pid_t> serverPidMap_;
|
||||||
|
|
||||||
|
PerfRecordSample() = default;
|
||||||
|
PerfRecordSample(const PerfRecordSample& sample);
|
||||||
|
// referenced input(p) in PerfRecordSample, require caller keep input(p) together
|
||||||
|
void Init(uint8_t* data, const perf_event_attr& attr) override;
|
||||||
|
|
||||||
StackId stackId_ {0};
|
StackId stackId_ {0};
|
||||||
bool removeStack_ {false};
|
bool removeStack_ {false};
|
||||||
inline static bool dumpRemoveStack_ {false};
|
static void SetDumpRemoveStack(bool dumpRemoveStack);
|
||||||
// referenced input(p) in PerfRecordSample, require caller keep input(p) together
|
static bool IsDumpRemoveStack();
|
||||||
PerfRecordSample(uint8_t *p, const perf_event_attr &attr);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent = 0) const override;
|
void DumpData(int indent = 0) const override;
|
||||||
void DumpLog(const std::string &prefix) const override;
|
void DumpLog(const std::string &prefix) const override;
|
||||||
@ -279,56 +271,50 @@ public:
|
|||||||
|
|
||||||
// only for UT
|
// only for UT
|
||||||
PerfRecordSample(bool inKernel, u32 pid, u32 tid, u64 period = 0, u64 time = 0, u64 id = 0)
|
PerfRecordSample(bool inKernel, u32 pid, u32 tid, u64 period = 0, u64 time = 0, u64 id = 0)
|
||||||
: PerfEventRecord(PERF_RECORD_SAMPLE, inKernel, "sample")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_SAMPLE, inKernel);
|
||||||
Clean();
|
Clean();
|
||||||
data_.pid = pid;
|
data_.pid = pid;
|
||||||
data_.tid = tid;
|
data_.tid = tid;
|
||||||
data_.period = period;
|
data_.period = period;
|
||||||
data_.time = time;
|
data_.time = time;
|
||||||
data_.id = 0;
|
data_.id = 0;
|
||||||
header.size = sizeof(header) + sizeof(data_);
|
header_.size = sizeof(header_) + sizeof(data_);
|
||||||
};
|
}
|
||||||
|
|
||||||
pid_t GetUstackServerPid();
|
pid_t GetUstackServerPid();
|
||||||
pid_t GetServerPidof(unsigned int ipNr);
|
pid_t GetServerPidof(unsigned int ipNr);
|
||||||
|
private:
|
||||||
|
static bool dumpRemoveStack_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordExit : public PerfEventRecord {
|
class PerfRecordExit : public PerfEventRecordTemplate<PerfRecordExitData, PERF_RECORD_TYPE_EXIT> {
|
||||||
public:
|
public:
|
||||||
PerfRecordExitData data_;
|
PerfRecordExit() = default;
|
||||||
|
|
||||||
explicit PerfRecordExit(uint8_t *p);
|
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordThrottle : public PerfEventRecord {
|
class PerfRecordThrottle : public PerfEventRecordTemplate<PerfRecordThrottleData, PERF_RECORD_TYPE_THROTTLE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordThrottleData data_;
|
PerfRecordThrottle() = default;
|
||||||
|
|
||||||
PerfRecordThrottle(uint8_t *p);
|
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordUnthrottle : public PerfEventRecord {
|
class PerfRecordUnthrottle : public PerfEventRecordTemplate<PerfRecordThrottleData, PERF_RECORD_TYPE_UNTHROTTLE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordThrottleData data_;
|
PerfRecordUnthrottle() = default;
|
||||||
|
|
||||||
explicit PerfRecordUnthrottle(uint8_t *p);
|
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerfRecordFork : public PerfEventRecord {
|
class PerfRecordFork : public PerfEventRecordTemplate<PerfRecordForkData, PERF_RECORD_TYPE_FORK> {
|
||||||
public:
|
public:
|
||||||
PerfRecordForkData data_;
|
PerfRecordFork() = default;
|
||||||
|
|
||||||
explicit PerfRecordFork(uint8_t *p);
|
|
||||||
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
@ -337,11 +323,10 @@ public:
|
|||||||
/*
|
/*
|
||||||
This record indicates a read event.
|
This record indicates a read event.
|
||||||
*/
|
*/
|
||||||
class PerfRecordRead : public PerfEventRecord {
|
class PerfRecordRead : public PerfEventRecordTemplate<PerfRecordReadData, PERF_RECORD_TYPE_READ> {
|
||||||
public:
|
public:
|
||||||
PerfRecordReadData data_;
|
PerfRecordRead() = default;
|
||||||
|
|
||||||
explicit PerfRecordRead(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
@ -365,12 +350,11 @@ public:
|
|||||||
if set, then the data returned has
|
if set, then the data returned has
|
||||||
overwritten previous data.
|
overwritten previous data.
|
||||||
*/
|
*/
|
||||||
class PerfRecordAux : public PerfEventRecord {
|
class PerfRecordAux : public PerfEventRecordTemplate<PerfRecordAuxData, PERF_RECORD_TYPE_AUX> {
|
||||||
public:
|
public:
|
||||||
uint64_t sampleType_ = SAMPLE_ID;
|
uint64_t sampleType_ = SAMPLE_ID;
|
||||||
PerfRecordAuxData data_;
|
PerfRecordAux() = default;
|
||||||
|
|
||||||
explicit PerfRecordAux(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
@ -386,11 +370,10 @@ public:
|
|||||||
tid thread ID of the thread starting an instruction
|
tid thread ID of the thread starting an instruction
|
||||||
trace.
|
trace.
|
||||||
*/
|
*/
|
||||||
class PerfRecordItraceStart : public PerfEventRecord {
|
class PerfRecordItraceStart : public PerfEventRecordTemplate<PerfRecordItraceStartData, PERF_RECORD_TYPE_ITRACESTART> {
|
||||||
public:
|
public:
|
||||||
PerfRecordItraceStartData data_;
|
PerfRecordItraceStart() = default;
|
||||||
|
|
||||||
explicit PerfRecordItraceStart(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
@ -400,11 +383,10 @@ public:
|
|||||||
record indicates some number of samples that may have
|
record indicates some number of samples that may have
|
||||||
been lost.
|
been lost.
|
||||||
*/
|
*/
|
||||||
class PerfRecordLostSamples : public PerfEventRecord {
|
class PerfRecordLostSamples : public PerfEventRecordTemplate<PerfRecordLostSamplesData, PERF_RECORD_TYPE_LOSTSAMPLE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordLostSamplesData data_;
|
PerfRecordLostSamples() = default;
|
||||||
|
|
||||||
explicit PerfRecordLostSamples(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
@ -415,12 +397,12 @@ public:
|
|||||||
indicates whether it was a context switch into or away
|
indicates whether it was a context switch into or away
|
||||||
from the current process.
|
from the current process.
|
||||||
*/
|
*/
|
||||||
class PerfRecordSwitch : public PerfEventRecord {
|
class PerfRecordSwitch : public PerfEventRecordTemplate<PerfRecordSwitchData, PERF_RECORD_TYPE_SWITCH> {
|
||||||
public:
|
public:
|
||||||
PerfRecordSwitchData data_;
|
PerfRecordSwitch() = default;
|
||||||
explicit PerfRecordSwitch(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData([[maybe_unused]] int indent) const override {};
|
void DumpData(int) const override {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -441,20 +423,30 @@ public:
|
|||||||
The thread ID of the previous (if switching in)
|
The thread ID of the previous (if switching in)
|
||||||
or next (if switching out) thread on the CPU.
|
or next (if switching out) thread on the CPU.
|
||||||
*/
|
*/
|
||||||
class PerfRecordSwitchCpuWide : public PerfEventRecord {
|
class PerfRecordSwitchCpuWide
|
||||||
|
: public PerfEventRecordTemplate<PerfRecordSwitchCpuWideData, PERF_RECORD_TYPE_SWITCHCPUWIDE> {
|
||||||
public:
|
public:
|
||||||
PerfRecordSwitchCpuWideData data_;
|
PerfRecordSwitchCpuWide() = default;
|
||||||
explicit PerfRecordSwitchCpuWide(uint8_t *p);
|
|
||||||
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
bool GetBinary(std::vector<uint8_t> &buf) const override;
|
||||||
void DumpData(int indent) const override;
|
void DumpData(int indent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfEventRecord(const int type, uint8_t *p,
|
class PerfRecordNull : public PerfEventRecordTemplate<PerfRecordSwitchCpuWideData, PERF_RECORD_TYPE_NULL> {
|
||||||
const perf_event_attr &attr);
|
public:
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfSampleFromCache(const int type, uint8_t *p,
|
PerfRecordNull() = default;
|
||||||
const perf_event_attr &attr);
|
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfSampleFromCacheMain(const int type, uint8_t *p,
|
bool GetBinary(std::vector<uint8_t>&) const override { return false; };
|
||||||
const perf_event_attr &attr);
|
void DumpData(int indent) const override {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class PerfEventRecordFactory {
|
||||||
|
public:
|
||||||
|
static PerfEventRecord& GetPerfEventRecord(PerfRecordType type, uint8_t* data,
|
||||||
|
const perf_event_attr& attr);
|
||||||
|
private:
|
||||||
|
static thread_local std::unordered_map<PerfRecordType, PerfEventRecord*> recordMap_;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void PushToBinary(bool condition, uint8_t *&p, const T &v);
|
void PushToBinary(bool condition, uint8_t *&p, const T &v);
|
||||||
|
@ -443,7 +443,7 @@ public:
|
|||||||
};
|
};
|
||||||
using StatCallBack =
|
using StatCallBack =
|
||||||
std::function<void(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &)>;
|
std::function<void(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &)>;
|
||||||
using RecordCallBack = std::function<bool(std::unique_ptr<PerfEventRecord>)>;
|
using RecordCallBack = std::function<bool(PerfEventRecord&)>;
|
||||||
|
|
||||||
void SetStatCallBack(StatCallBack reportCallBack);
|
void SetStatCallBack(StatCallBack reportCallBack);
|
||||||
void SetRecordCallBack(RecordCallBack recordCallBack);
|
void SetRecordCallBack(RecordCallBack recordCallBack);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
namespace OHOS {
|
namespace OHOS {
|
||||||
namespace Developtools {
|
namespace Developtools {
|
||||||
namespace HiPerf {
|
namespace HiPerf {
|
||||||
using ProcessRecordCB = const std::function<bool(std::unique_ptr<PerfEventRecord> record)>;
|
using ProcessRecordCB = const std::function<bool(PerfEventRecord& record)>;
|
||||||
// read record from data file, like perf.data.
|
// read record from data file, like perf.data.
|
||||||
// format of file follow
|
// format of file follow
|
||||||
// tools/perf/Documentation/perf.data-file-format.txt
|
// tools/perf/Documentation/perf.data-file-format.txt
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
uint GetRecordCount() const;
|
uint GetRecordCount() const;
|
||||||
std::chrono::microseconds writeTimes_ = std::chrono::microseconds::zero();
|
std::chrono::microseconds writeTimes_ = std::chrono::microseconds::zero();
|
||||||
|
|
||||||
using ProcessRecordCB = const std::function<bool(std::unique_ptr<PerfEventRecord> record)>;
|
using ProcessRecordCB = const std::function<bool(PerfEventRecord& record)>;
|
||||||
bool ReadDataSection(ProcessRecordCB &callback);
|
bool ReadDataSection(ProcessRecordCB &callback);
|
||||||
bool ReadRecords(ProcessRecordCB &callback);
|
bool ReadRecords(ProcessRecordCB &callback);
|
||||||
bool Read(void *buf, size_t len);
|
bool Read(void *buf, size_t len);
|
||||||
|
@ -107,10 +107,10 @@ private:
|
|||||||
void DumpPrintFileHeader(int indent = 0);
|
void DumpPrintFileHeader(int indent = 0);
|
||||||
void DumpAttrPortion(int indent = 0);
|
void DumpAttrPortion(int indent = 0);
|
||||||
void DumpDataPortion(int indent = 0);
|
void DumpDataPortion(int indent = 0);
|
||||||
void DumpCallChain(int indent, std::unique_ptr<PerfRecordSample> &sample);
|
void DumpCallChain(int indent, const PerfRecordSample& sample);
|
||||||
void DumpFeaturePortion(int indent = 0);
|
void DumpFeaturePortion(int indent = 0);
|
||||||
void DumpUniqueStackTableNode(int indent, const PerfFileSectionUniStackTable &uniStackTable);
|
void DumpUniqueStackTableNode(int indent, const PerfFileSectionUniStackTable &uniStackTable);
|
||||||
void ExprotUserData(std::unique_ptr<PerfEventRecord> &record);
|
void ExprotUserData(PerfEventRecord& record);
|
||||||
void ExprotUserStack(const PerfRecordSample &recordSample);
|
void ExprotUserStack(const PerfRecordSample &recordSample);
|
||||||
void PrintHeaderInfo(const int &indent);
|
void PrintHeaderInfo(const int &indent);
|
||||||
void PrintSymbolFile(const int &indent, const SymbolFileStruct &symbolFileStruct);
|
void PrintSymbolFile(const int &indent, const SymbolFileStruct &symbolFileStruct);
|
||||||
|
@ -303,8 +303,8 @@ private:
|
|||||||
bool isSpe_ = false;
|
bool isSpe_ = false;
|
||||||
|
|
||||||
// callback to process record
|
// callback to process record
|
||||||
bool ProcessRecord(std::unique_ptr<PerfEventRecord>);
|
bool ProcessRecord(PerfEventRecord& record);
|
||||||
bool SaveRecord(std::unique_ptr<PerfEventRecord>, bool ptrReleaseFlag = false);
|
bool SaveRecord(const PerfEventRecord& record, bool ptrReleaseFlag = false);
|
||||||
|
|
||||||
// file format like as 0,1-3,4-6,7,8
|
// file format like as 0,1-3,4-6,7,8
|
||||||
uint32_t GetCountFromFile(const std::string &fileName);
|
uint32_t GetCountFromFile(const std::string &fileName);
|
||||||
@ -327,7 +327,7 @@ private:
|
|||||||
void ReportTime();
|
void ReportTime();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool CollectionSymbol(std::unique_ptr<PerfEventRecord> record);
|
bool CollectionSymbol(PerfEventRecord& record);
|
||||||
void CollectSymbol(PerfRecordSample *sample);
|
void CollectSymbol(PerfRecordSample *sample);
|
||||||
bool SetPerfLimit(const std::string& file, int value, std::function<bool (int, int)> const& cmd,
|
bool SetPerfLimit(const std::string& file, int value, std::function<bool (int, int)> const& cmd,
|
||||||
const std::string& param);
|
const std::string& param);
|
||||||
|
@ -107,7 +107,7 @@ public:
|
|||||||
bool ParseOption(std::vector<std::string> &args) override;
|
bool ParseOption(std::vector<std::string> &args) override;
|
||||||
void DumpOptions(void) const override;
|
void DumpOptions(void) const override;
|
||||||
static bool RegisterSubCommandReport(void);
|
static bool RegisterSubCommandReport(void);
|
||||||
bool RecordCallBack(std::unique_ptr<PerfEventRecord> record);
|
bool RecordCallBack(PerfEventRecord& record);
|
||||||
|
|
||||||
~SubCommandReport();
|
~SubCommandReport();
|
||||||
|
|
||||||
|
@ -345,29 +345,6 @@ bool IsArkJsFile(const std::string& filepath);
|
|||||||
std::string GetProcessName(int pid);
|
std::string GetProcessName(int pid);
|
||||||
bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
|
bool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
|
||||||
bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
|
bool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
|
||||||
|
|
||||||
template <typename Func>
|
|
||||||
class ScopeGuard {
|
|
||||||
public:
|
|
||||||
explicit ScopeGuard(Func&& fn)
|
|
||||||
: fn_(fn) {}
|
|
||||||
~ScopeGuard()
|
|
||||||
{
|
|
||||||
fn_();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
Func fn_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ScopeGuardOnExit {};
|
|
||||||
template <typename Func>
|
|
||||||
static inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn)
|
|
||||||
{
|
|
||||||
return ScopeGuard<Func>(std::forward<Func>(fn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ON_SCOPE_EXIT \
|
|
||||||
auto __onGuardExit__ = ScopeGuardOnExit{} + [&]
|
|
||||||
} // namespace HiPerf
|
} // namespace HiPerf
|
||||||
} // namespace Developtools
|
} // namespace Developtools
|
||||||
} // namespace OHOS
|
} // namespace OHOS
|
||||||
|
@ -51,7 +51,7 @@ public:
|
|||||||
// from the record , it will call back to write some Simulated Record
|
// from the record , it will call back to write some Simulated Record
|
||||||
// case 1. some mmap will be create when it read mmaps for each new process (from record sample)
|
// case 1. some mmap will be create when it read mmaps for each new process (from record sample)
|
||||||
|
|
||||||
using RecordCallBack = std::function<bool(std::unique_ptr<PerfEventRecord>)>;
|
using RecordCallBack = std::function<bool(PerfEventRecord&)>;
|
||||||
using CollectSymbolCallBack = std::function<void(PerfRecordSample*)>;
|
using CollectSymbolCallBack = std::function<void(PerfRecordSample*)>;
|
||||||
|
|
||||||
void SetRecordMode(RecordCallBack recordCallBack);
|
void SetRecordMode(RecordCallBack recordCallBack);
|
||||||
|
@ -24,94 +24,50 @@ namespace OHOS {
|
|||||||
namespace Developtools {
|
namespace Developtools {
|
||||||
namespace HiPerf {
|
namespace HiPerf {
|
||||||
|
|
||||||
void *g_sampleMemCache = nullptr; // for read record from buf thread
|
bool PerfRecordSample::dumpRemoveStack_ = false;
|
||||||
void *g_sampleMemCacheMain = nullptr; // for main thread:collecttionsymbol
|
thread_local std::unordered_map<PerfRecordType, PerfEventRecord*> PerfEventRecordFactory::recordMap_ = {};
|
||||||
constexpr size_t SAMPLE_CACHE_SIZE = 4 * 1024;
|
|
||||||
|
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfEventRecord(const int type, uint8_t *p,
|
static PerfEventRecord* CreatePerfEventRecord(PerfRecordType type)
|
||||||
const perf_event_attr &attr)
|
|
||||||
{
|
{
|
||||||
HLOG_ASSERT(p);
|
|
||||||
uint8_t *data = p;
|
|
||||||
|
|
||||||
// check kernel
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PERF_RECORD_SAMPLE:
|
case PERF_RECORD_SAMPLE:
|
||||||
return std::make_unique<PerfRecordSample>(data, attr);
|
return new PerfRecordSample();
|
||||||
case PERF_RECORD_MMAP:
|
case PERF_RECORD_MMAP:
|
||||||
return std::make_unique<PerfRecordMmap>(data);
|
return new PerfRecordMmap();
|
||||||
case PERF_RECORD_MMAP2:
|
case PERF_RECORD_MMAP2:
|
||||||
return std::make_unique<PerfRecordMmap2>(data);
|
return new PerfRecordMmap2();
|
||||||
case PERF_RECORD_LOST:
|
case PERF_RECORD_LOST:
|
||||||
return std::make_unique<PerfRecordLost>(data);
|
return new PerfRecordLost();
|
||||||
case PERF_RECORD_COMM:
|
case PERF_RECORD_COMM:
|
||||||
return std::make_unique<PerfRecordComm>(data);
|
return new PerfRecordComm();
|
||||||
case PERF_RECORD_EXIT:
|
case PERF_RECORD_EXIT:
|
||||||
return std::make_unique<PerfRecordExit>(data);
|
return new PerfRecordExit();
|
||||||
case PERF_RECORD_THROTTLE:
|
case PERF_RECORD_THROTTLE:
|
||||||
return std::make_unique<PerfRecordThrottle>(data);
|
return new PerfRecordThrottle();
|
||||||
case PERF_RECORD_UNTHROTTLE:
|
case PERF_RECORD_UNTHROTTLE:
|
||||||
return std::make_unique<PerfRecordUnthrottle>(data);
|
return new PerfRecordUnthrottle();
|
||||||
case PERF_RECORD_FORK:
|
case PERF_RECORD_FORK:
|
||||||
return std::make_unique<PerfRecordFork>(data);
|
return new PerfRecordFork();
|
||||||
case PERF_RECORD_READ:
|
case PERF_RECORD_READ:
|
||||||
return std::make_unique<PerfRecordRead>(data);
|
return new PerfRecordRead();
|
||||||
case PERF_RECORD_AUX:
|
case PERF_RECORD_AUX:
|
||||||
return std::make_unique<PerfRecordAux>(data);
|
return new PerfRecordAux();
|
||||||
case PERF_RECORD_AUXTRACE:
|
case PERF_RECORD_AUXTRACE:
|
||||||
return std::make_unique<PerfRecordAuxtrace>(data);
|
return new PerfRecordAuxtrace();
|
||||||
case PERF_RECORD_ITRACE_START:
|
case PERF_RECORD_ITRACE_START:
|
||||||
return std::make_unique<PerfRecordItraceStart>(data);
|
return new PerfRecordItraceStart();
|
||||||
case PERF_RECORD_LOST_SAMPLES:
|
case PERF_RECORD_LOST_SAMPLES:
|
||||||
return std::make_unique<PerfRecordLostSamples>(data);
|
return new PerfRecordLostSamples();
|
||||||
case PERF_RECORD_SWITCH:
|
case PERF_RECORD_SWITCH:
|
||||||
return std::make_unique<PerfRecordSwitch>(data);
|
return new PerfRecordSwitch();
|
||||||
case PERF_RECORD_SWITCH_CPU_WIDE:
|
case PERF_RECORD_SWITCH_CPU_WIDE:
|
||||||
return std::make_unique<PerfRecordSwitchCpuWide>(data);
|
return new PerfRecordSwitchCpuWide();
|
||||||
default:
|
default:
|
||||||
HLOGE("unknown record type %d\n", type);
|
HLOGE("unknown record type %d\n", type);
|
||||||
return nullptr;
|
return new PerfRecordNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfSampleFromCache(const int type, uint8_t *p,
|
|
||||||
const perf_event_attr &attr)
|
|
||||||
{
|
|
||||||
HLOG_ASSERT(p);
|
|
||||||
uint8_t *data = p;
|
|
||||||
|
|
||||||
if (type == PERF_RECORD_SAMPLE) {
|
|
||||||
if (g_sampleMemCache != nullptr) {
|
|
||||||
memset_s(g_sampleMemCache, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
|
|
||||||
return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCache) PerfRecordSample(data, attr));
|
|
||||||
} else {
|
|
||||||
g_sampleMemCache = std::malloc(SAMPLE_CACHE_SIZE);
|
|
||||||
memset_s(g_sampleMemCache, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
|
|
||||||
return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCache) PerfRecordSample(data, attr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return GetPerfEventRecord(type, p, attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<PerfEventRecord> GetPerfSampleFromCacheMain(const int type, uint8_t *p,
|
|
||||||
const perf_event_attr &attr)
|
|
||||||
{
|
|
||||||
HLOG_ASSERT(p);
|
|
||||||
uint8_t *data = p;
|
|
||||||
|
|
||||||
if (type == PERF_RECORD_SAMPLE) {
|
|
||||||
if (g_sampleMemCacheMain != nullptr) {
|
|
||||||
memset_s(g_sampleMemCacheMain, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
|
|
||||||
return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCacheMain) PerfRecordSample(data, attr));
|
|
||||||
} else {
|
|
||||||
g_sampleMemCacheMain = std::malloc(SAMPLE_CACHE_SIZE);
|
|
||||||
memset_s(g_sampleMemCacheMain, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
|
|
||||||
return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCacheMain) PerfRecordSample(data, attr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return GetPerfEventRecord(type, p, attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void PushToBinary(bool condition, uint8_t *&p, const T &v)
|
inline void PushToBinary(bool condition, uint8_t *&p, const T &v)
|
||||||
{
|
{
|
||||||
@ -153,31 +109,29 @@ inline void PopFromBinary2(bool condition, uint8_t *&p, T1 &v1, T2 &v2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PerfEventRecord
|
// PerfEventRecord
|
||||||
PerfEventRecord::PerfEventRecord(perf_event_type type, bool inKernel, const std::string &name)
|
void PerfEventRecord::Init(perf_event_type type, bool inKernel)
|
||||||
: name_(name)
|
|
||||||
{
|
{
|
||||||
header.type = type;
|
header_.type = type;
|
||||||
header.misc = inKernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER;
|
header_.misc = inKernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER;
|
||||||
header.size = sizeof(header);
|
header_.size = sizeof(header_);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PerfEventRecord::Init(perf_event_hiperf_ext_type type)
|
||||||
|
{
|
||||||
|
header_.type = type;
|
||||||
|
header_.misc = PERF_RECORD_MISC_USER;
|
||||||
|
header_.size = sizeof(header_);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfEventRecord::PerfEventRecord(perf_event_hiperf_ext_type type, const std::string &name)
|
void PerfEventRecord::InitHeader(uint8_t* p)
|
||||||
: name_(name)
|
|
||||||
{
|
|
||||||
header.type = type;
|
|
||||||
header.misc = PERF_RECORD_MISC_USER;
|
|
||||||
header.size = sizeof(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
PerfEventRecord::PerfEventRecord(uint8_t *p, const std::string &name) : name_(name)
|
|
||||||
{
|
{
|
||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
header.type = PERF_RECORD_MMAP;
|
header_.type = PERF_RECORD_MMAP;
|
||||||
header.misc = PERF_RECORD_MISC_USER;
|
header_.misc = PERF_RECORD_MISC_USER;
|
||||||
header.size = 0;
|
header_.size = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
header = *(reinterpret_cast<perf_event_header *>(p));
|
header_ = *(reinterpret_cast<perf_event_header*>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfEventRecord::GetHeaderBinary(std::vector<uint8_t> &buf) const
|
void PerfEventRecord::GetHeaderBinary(std::vector<uint8_t> &buf) const
|
||||||
@ -186,7 +140,7 @@ void PerfEventRecord::GetHeaderBinary(std::vector<uint8_t> &buf) const
|
|||||||
buf.resize(GetHeaderSize());
|
buf.resize(GetHeaderSize());
|
||||||
}
|
}
|
||||||
uint8_t *p = buf.data();
|
uint8_t *p = buf.data();
|
||||||
*(reinterpret_cast<perf_event_header *>(p)) = header;
|
*(reinterpret_cast<perf_event_header*>(p)) = header_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfEventRecord::Dump(int indent, std::string outputFilename, FILE *outputDump) const
|
void PerfEventRecord::Dump(int indent, std::string outputFilename, FILE *outputDump) const
|
||||||
@ -202,14 +156,14 @@ void PerfEventRecord::Dump(int indent, std::string outputFilename, FILE *outputD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PRINT_INDENT(indent, "\n");
|
PRINT_INDENT(indent, "\n");
|
||||||
PRINT_INDENT(indent, "record %s: type %u, misc %u, size %zu\n", GetName().c_str(), GetType(),
|
PRINT_INDENT(indent, "record %s: type %u, misc %u, size %zu\n", GetName(), GetType(),
|
||||||
GetMisc(), GetSize());
|
GetMisc(), GetSize());
|
||||||
DumpData(indent + 1);
|
DumpData(indent + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfEventRecord::DumpLog(const std::string &prefix) const
|
void PerfEventRecord::DumpLog(const std::string &prefix) const
|
||||||
{
|
{
|
||||||
HLOGV("%s: record %s: type %u, misc %u, size %zu\n", prefix.c_str(), GetName().c_str(),
|
HLOGV("%s: record %s: type %u, misc %u, size %zu\n", prefix.c_str(), GetName(),
|
||||||
GetType(), GetMisc(), GetSize());
|
GetType(), GetMisc(), GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,22 +171,15 @@ std::vector<u64> PerfRecordSample::ips_ = {};
|
|||||||
std::vector<DfxFrame> PerfRecordSample::callFrames_ = {};
|
std::vector<DfxFrame> PerfRecordSample::callFrames_ = {};
|
||||||
std::vector<pid_t> PerfRecordSample::serverPidMap_ = {};
|
std::vector<pid_t> PerfRecordSample::serverPidMap_ = {};
|
||||||
|
|
||||||
PerfRecordAuxtrace::PerfRecordAuxtrace(uint8_t *p) : PerfEventRecord(p, "auxtrace")
|
void PerfRecordAuxtrace::Init(uint8_t* data, const perf_event_attr& attr)
|
||||||
{
|
{
|
||||||
if (header.size >= sizeof(header)) {
|
PerfEventRecordTemplate::Init(data);
|
||||||
size_t copySize = header.size - sizeof(header);
|
rawData_ = data + header_.size;
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordAuxtrace retren failed !!!");
|
|
||||||
}
|
|
||||||
rawData_ = p + header.size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordAuxtrace::PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32 idx, u32 tid, u32 cpu, u32 pid)
|
PerfRecordAuxtrace::PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32 idx, u32 tid, u32 cpu, u32 pid)
|
||||||
: PerfEventRecord(PERF_RECORD_AUXTRACE, "auxtrace")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_AUXTRACE);
|
||||||
data_.size = size;
|
data_.size = size;
|
||||||
data_.offset = offset;
|
data_.offset = offset;
|
||||||
data_.reference = reference;
|
data_.reference = reference;
|
||||||
@ -241,19 +188,19 @@ PerfRecordAuxtrace::PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32
|
|||||||
data_.cpu = cpu;
|
data_.cpu = cpu;
|
||||||
data_.reserved__ = pid;
|
data_.reserved__ = pid;
|
||||||
|
|
||||||
header.size = sizeof(header) + sizeof(data_);
|
header_.size = sizeof(header_) + sizeof(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PerfRecordAuxtrace::GetBinary1(std::vector<uint8_t> &buf) const
|
bool PerfRecordAuxtrace::GetBinary1(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < header.size) {
|
if (buf.size() < header_.size) {
|
||||||
buf.resize(header.size);
|
buf.resize(header_.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetHeaderBinary(buf);
|
GetHeaderBinary(buf);
|
||||||
uint8_t *p = buf.data() + GetHeaderSize();
|
uint8_t *p = buf.data() + GetHeaderSize();
|
||||||
|
|
||||||
size_t copySize = header.size - GetHeaderSize();
|
size_t copySize = header_.size - GetHeaderSize();
|
||||||
if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
|
if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
|
||||||
HLOGE("memcpy_s return failed");
|
HLOGE("memcpy_s return failed");
|
||||||
return false;
|
return false;
|
||||||
@ -270,12 +217,12 @@ bool PerfRecordAuxtrace::GetBinary(std::vector<uint8_t> &buf) const
|
|||||||
GetHeaderBinary(buf);
|
GetHeaderBinary(buf);
|
||||||
uint8_t *p = buf.data() + GetHeaderSize();
|
uint8_t *p = buf.data() + GetHeaderSize();
|
||||||
|
|
||||||
size_t copySize = header.size - GetHeaderSize();
|
size_t copySize = header_.size - GetHeaderSize();
|
||||||
if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
|
if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
|
||||||
HLOGE("memcpy_s return failed");
|
HLOGE("memcpy_s return failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
p += header.size - GetHeaderSize();
|
p += header_.size - GetHeaderSize();
|
||||||
if (memcpy_s(p, data_.size, static_cast<uint8_t *>(rawData_), data_.size) != 0) {
|
if (memcpy_s(p, data_.size, static_cast<uint8_t *>(rawData_), data_.size) != 0) {
|
||||||
HLOGE("memcpy_s return failed");
|
HLOGE("memcpy_s return failed");
|
||||||
return false;
|
return false;
|
||||||
@ -302,13 +249,13 @@ void PerfRecordAuxtrace::DumpLog(const std::string &prefix) const
|
|||||||
|
|
||||||
size_t PerfRecordAuxtrace::GetSize() const
|
size_t PerfRecordAuxtrace::GetSize() const
|
||||||
{
|
{
|
||||||
return header.size + data_.size;
|
return header_.size + data_.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfRecordSample::DumpLog(const std::string &prefix) const
|
void PerfRecordSample::DumpLog(const std::string &prefix) const
|
||||||
{
|
{
|
||||||
HLOGV("%s: SAMPLE: id= %llu size %d pid %u tid %u ips %llu regs %llu, stacks %llu time %llu",
|
HLOGV("%s: SAMPLE: id= %llu size %d pid %u tid %u ips %llu regs %llu, stacks %llu time %llu",
|
||||||
prefix.c_str(), data_.sample_id, header.size, data_.pid, data_.tid, data_.nr,
|
prefix.c_str(), data_.sample_id, header_.size, data_.pid, data_.tid, data_.nr,
|
||||||
data_.reg_nr, data_.dyn_size, data_.time);
|
data_.reg_nr, data_.dyn_size, data_.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,15 +299,15 @@ void PerfRecordSample::ReplaceWithCallStack(size_t originalSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sampleType_ & PERF_SAMPLE_REGS_USER) {
|
if (sampleType_ & PERF_SAMPLE_REGS_USER) {
|
||||||
header.size -= data_.reg_nr * sizeof(u64);
|
header_.size -= data_.reg_nr * sizeof(u64);
|
||||||
data_.reg_nr = 0;
|
data_.reg_nr = 0;
|
||||||
data_.user_abi = 0;
|
data_.user_abi = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sampleType_ & PERF_SAMPLE_STACK_USER) {
|
if (sampleType_ & PERF_SAMPLE_STACK_USER) {
|
||||||
// 1. remove the user stack
|
// 1. remove the user stack
|
||||||
header.size -= data_.stack_size;
|
header_.size -= data_.stack_size;
|
||||||
header.size -= sizeof(data_.dyn_size);
|
header_.size -= sizeof(data_.dyn_size);
|
||||||
|
|
||||||
// 2. clean the size
|
// 2. clean the size
|
||||||
data_.stack_size = 0;
|
data_.stack_size = 0;
|
||||||
@ -371,11 +318,11 @@ void PerfRecordSample::ReplaceWithCallStack(size_t originalSize)
|
|||||||
HLOGV("ips change from %llu -> %zu", data_.nr, ips_.size());
|
HLOGV("ips change from %llu -> %zu", data_.nr, ips_.size());
|
||||||
|
|
||||||
// 3. remove the nr size
|
// 3. remove the nr size
|
||||||
header.size -= data_.nr * sizeof(u64);
|
header_.size -= data_.nr * sizeof(u64);
|
||||||
|
|
||||||
// 4. add new nr size
|
// 4. add new nr size
|
||||||
data_.nr = ips_.size();
|
data_.nr = ips_.size();
|
||||||
header.size += data_.nr * sizeof(u64);
|
header_.size += data_.nr * sizeof(u64);
|
||||||
|
|
||||||
// 5. change ips potin to our ips array and hold it.
|
// 5. change ips potin to our ips array and hold it.
|
||||||
data_.ips = ips_.data();
|
data_.ips = ips_.data();
|
||||||
@ -386,20 +333,21 @@ void PerfRecordSample::ReplaceWithCallStack(size_t originalSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordSample::PerfRecordSample(uint8_t *p, const perf_event_attr &attr)
|
void PerfRecordSample::Init(uint8_t *p, const perf_event_attr &attr)
|
||||||
: PerfEventRecord(p, "sample")
|
|
||||||
{
|
{
|
||||||
if (p == nullptr) {
|
PerfEventRecord::InitHeader(p);
|
||||||
HLOG_ASSERT(p);
|
|
||||||
return;
|
HLOG_ASSERT(p != nullptr);
|
||||||
}
|
// clear the vector data
|
||||||
// clear the static vector data
|
|
||||||
Clean();
|
Clean();
|
||||||
sampleType_ = attr.sample_type;
|
sampleType_ = attr.sample_type;
|
||||||
|
skipKernel_ = 0;
|
||||||
|
skipPid_ = 0;
|
||||||
|
stackId_ = {0};
|
||||||
|
removeStack_ = false;
|
||||||
|
data_ = {};
|
||||||
uint8_t *start = p;
|
uint8_t *start = p;
|
||||||
|
p += sizeof(header_);
|
||||||
p += sizeof(header);
|
|
||||||
|
|
||||||
// parse record according SAMPLE_TYPE
|
// parse record according SAMPLE_TYPE
|
||||||
PopFromBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id);
|
PopFromBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id);
|
||||||
@ -446,7 +394,7 @@ PerfRecordSample::PerfRecordSample(uint8_t *p, const perf_event_attr &attr)
|
|||||||
p += data_.stack_size;
|
p += data_.stack_size;
|
||||||
PopFromBinary(true, p, data_.dyn_size);
|
PopFromBinary(true, p, data_.dyn_size);
|
||||||
}
|
}
|
||||||
uint32_t remain = header.size - (p - start);
|
uint32_t remain = header_.size - (p - start);
|
||||||
if (data_.nr == 0 && dumpRemoveStack_ && remain == sizeof(stackId_)) {
|
if (data_.nr == 0 && dumpRemoveStack_ && remain == sizeof(stackId_)) {
|
||||||
PopFromBinary(true, p, stackId_.value);
|
PopFromBinary(true, p, stackId_.value);
|
||||||
}
|
}
|
||||||
@ -603,23 +551,11 @@ void PerfRecordSample::Clean()
|
|||||||
serverPidMap_.clear();
|
serverPidMap_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordMmap::PerfRecordMmap(uint8_t *p) : PerfEventRecord(p, "mmap")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordMmap retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
PerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
: PerfEventRecord(PERF_RECORD_MMAP, inKernel, "mmap")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_MMAP, inKernel);
|
||||||
|
|
||||||
data_.pid = pid;
|
data_.pid = pid;
|
||||||
data_.tid = tid;
|
data_.tid = tid;
|
||||||
data_.addr = addr;
|
data_.addr = addr;
|
||||||
@ -629,7 +565,7 @@ PerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 le
|
|||||||
HLOGE("strncpy_s failed");
|
HLOGE("strncpy_s failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1;
|
header_.size = sizeof(header_) + sizeof(data_) - KILO + filename.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PerfRecordMmap::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordMmap::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
@ -661,27 +597,14 @@ void PerfRecordMmap::DumpData(int indent) const
|
|||||||
void PerfRecordMmap::DumpLog(const std::string &prefix) const
|
void PerfRecordMmap::DumpLog(const std::string &prefix) const
|
||||||
{
|
{
|
||||||
HLOGV("%s: MMAP: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
|
HLOGV("%s: MMAP: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
|
||||||
header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len, data_.pgoff);
|
header_.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len, data_.pgoff);
|
||||||
}
|
|
||||||
|
|
||||||
PerfRecordMmap2::PerfRecordMmap2(uint8_t *p) : PerfEventRecord(p, "mmap2")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordMmap2 retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
|
||||||
u32 maj, u32 min, u64 ino, u32 prot, u32 flags,
|
u32 maj, u32 min, u64 ino, u32 prot, u32 flags,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
: PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_MMAP2, inKernel);
|
||||||
data_.pid = pid;
|
data_.pid = pid;
|
||||||
data_.tid = tid;
|
data_.tid = tid;
|
||||||
data_.addr = addr;
|
data_.addr = addr;
|
||||||
@ -697,12 +620,12 @@ PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64
|
|||||||
HLOGE("strncpy_s failed");
|
HLOGE("strncpy_s failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1;
|
header_.size = sizeof(header_) + sizeof(data_) - KILO + filename.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, std::shared_ptr<DfxMap> item)
|
PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, std::shared_ptr<DfxMap> item)
|
||||||
: PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_MMAP2, inKernel);
|
||||||
data_.pid = pid;
|
data_.pid = pid;
|
||||||
data_.tid = tid;
|
data_.tid = tid;
|
||||||
if (item != nullptr) {
|
if (item != nullptr) {
|
||||||
@ -720,7 +643,7 @@ PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, std::shared_pt
|
|||||||
HLOGE("strncpy_s failed");
|
HLOGE("strncpy_s failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
header.size = sizeof(header) + sizeof(data_) - KILO + item->name.size() + 1;
|
header_.size = sizeof(header_) + sizeof(data_) - KILO + item->name.size() + 1;
|
||||||
} else {
|
} else {
|
||||||
data_.addr = 0;
|
data_.addr = 0;
|
||||||
data_.len = 0;
|
data_.len = 0;
|
||||||
@ -763,26 +686,14 @@ void PerfRecordMmap2::DumpData(int indent) const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfRecordMmap2::DumpLog(const std::string &prefix) const
|
void PerfRecordMmap2::DumpLog(const std::string &prefix) const
|
||||||
{
|
{
|
||||||
HLOGV("%s: MMAP2: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
|
HLOGV("%s: MMAP2: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
|
||||||
header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len,
|
header_.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len,
|
||||||
data_.pgoff);
|
data_.pgoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordLost::PerfRecordLost(uint8_t *p) : PerfEventRecord(p, "lost")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordLost retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordLost::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordLost::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -803,29 +714,17 @@ void PerfRecordLost::DumpData(int indent) const
|
|||||||
PRINT_INDENT(indent, "id %llu, lost %llu\n", data_.id, data_.lost);
|
PRINT_INDENT(indent, "id %llu, lost %llu\n", data_.id, data_.lost);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordComm::PerfRecordComm(uint8_t *p) : PerfEventRecord(p, "comm")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordComm retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PerfRecordComm::PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm)
|
PerfRecordComm::PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm)
|
||||||
: PerfEventRecord(PERF_RECORD_COMM, inKernel, "comm")
|
|
||||||
{
|
{
|
||||||
|
PerfEventRecord::Init(PERF_RECORD_COMM, inKernel);
|
||||||
data_.pid = pid;
|
data_.pid = pid;
|
||||||
data_.tid = tid;
|
data_.tid = tid;
|
||||||
if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != 0) {
|
if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != 0) {
|
||||||
HLOGE("strncpy_s failed !!!");
|
HLOGE("strncpy_s failed !!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
header.size = sizeof(header) + sizeof(data_) - KILO + comm.size() + 1;
|
header_.size = sizeof(header_) + sizeof(data_) - KILO + comm.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PerfRecordComm::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordComm::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
@ -854,17 +753,31 @@ void PerfRecordComm::DumpLog(const std::string &prefix) const
|
|||||||
HLOGV("pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm);
|
HLOGV("pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordExit::PerfRecordExit(uint8_t *p) : PerfEventRecord(p, "exit")
|
PerfRecordSample::PerfRecordSample(const PerfRecordSample& sample)
|
||||||
{
|
{
|
||||||
size_t dataSize = GetSize();
|
header_ = sample.header_;
|
||||||
if (dataSize >= sizeof(header)) {
|
data_ = sample.data_;
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
sampleType_ = sample.sampleType_;
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
skipKernel_ = sample.skipKernel_;
|
||||||
}
|
skipPid_ = sample.skipPid_;
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordExit retren failed !!!");
|
ips_ = sample.ips_;
|
||||||
}
|
callFrames_ = sample.callFrames_;
|
||||||
|
serverPidMap_ = sample.serverPidMap_;
|
||||||
|
|
||||||
|
stackId_ = sample.stackId_;
|
||||||
|
removeStack_ = sample.removeStack_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerfRecordSample::SetDumpRemoveStack(bool dumpRemoveStack)
|
||||||
|
{
|
||||||
|
dumpRemoveStack_ = dumpRemoveStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PerfRecordSample::IsDumpRemoveStack()
|
||||||
|
{
|
||||||
|
return dumpRemoveStack_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PerfRecordExit::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordExit::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
@ -887,19 +800,6 @@ void PerfRecordExit::DumpData(int indent) const
|
|||||||
data_.tid, data_.ptid, data_.time);
|
data_.tid, data_.ptid, data_.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordThrottle::PerfRecordThrottle(uint8_t *p) : PerfEventRecord(p, "throttle")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordThrottle retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordThrottle::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordThrottle::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -920,19 +820,6 @@ void PerfRecordThrottle::DumpData(int indent) const
|
|||||||
data_.stream_id);
|
data_.stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordUnthrottle::PerfRecordUnthrottle(uint8_t *p) : PerfEventRecord(p, "unthrottle")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordUnthrottle retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordUnthrottle::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordUnthrottle::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -946,25 +833,13 @@ bool PerfRecordUnthrottle::GetBinary(std::vector<uint8_t> &buf) const
|
|||||||
*pDest = data_;
|
*pDest = data_;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfRecordUnthrottle::DumpData(int indent) const
|
void PerfRecordUnthrottle::DumpData(int indent) const
|
||||||
{
|
{
|
||||||
PRINT_INDENT(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id,
|
PRINT_INDENT(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id,
|
||||||
data_.stream_id);
|
data_.stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordFork::PerfRecordFork(uint8_t *p) : PerfEventRecord(p, "fork")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordFork retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordFork::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordFork::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -985,19 +860,6 @@ void PerfRecordFork::DumpData(int indent) const
|
|||||||
data_.ptid);
|
data_.ptid);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordRead::PerfRecordRead(uint8_t *p) : PerfEventRecord(p, "read")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordRead retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordRead::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordRead::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1019,19 +881,6 @@ void PerfRecordRead::DumpData(int indent) const
|
|||||||
data_.values.value, data_.values.timeEnabled, data_.values.timeRunning, data_.values.id);
|
data_.values.value, data_.values.timeEnabled, data_.values.timeRunning, data_.values.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordAux::PerfRecordAux(uint8_t *p) : PerfEventRecord(p, "aux")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordAux retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordAux::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordAux::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1061,19 +910,6 @@ void PerfRecordAux::DumpData(int indent) const
|
|||||||
data_.sample_id.time);
|
data_.sample_id.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordItraceStart::PerfRecordItraceStart(uint8_t *p) : PerfEventRecord(p, "itraceStart")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordItraceStart retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordItraceStart::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordItraceStart::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1093,19 +929,6 @@ void PerfRecordItraceStart::DumpData(int indent) const
|
|||||||
PRINT_INDENT(indent, "pid %u, tid %u\n", data_.pid, data_.tid);
|
PRINT_INDENT(indent, "pid %u, tid %u\n", data_.pid, data_.tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordLostSamples::PerfRecordLostSamples(uint8_t *p) : PerfEventRecord(p, "lostSamples")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordLostSamples retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordLostSamples::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordLostSamples::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1125,19 +948,6 @@ void PerfRecordLostSamples::DumpData(int indent) const
|
|||||||
PRINT_INDENT(indent, "lost %llu\n", data_.lost);
|
PRINT_INDENT(indent, "lost %llu\n", data_.lost);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordSwitch::PerfRecordSwitch(uint8_t *p) : PerfEventRecord(p, "switch")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordSwitch retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordSwitch::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordSwitch::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1152,19 +962,6 @@ bool PerfRecordSwitch::GetBinary(std::vector<uint8_t> &buf) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfRecordSwitchCpuWide::PerfRecordSwitchCpuWide(uint8_t *p) : PerfEventRecord(p, "switchCpuWide")
|
|
||||||
{
|
|
||||||
size_t dataSize = GetSize();
|
|
||||||
if (dataSize >= sizeof(header)) {
|
|
||||||
size_t copySize = dataSize - sizeof(header);
|
|
||||||
if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
|
|
||||||
HLOGE("memcpy_s retren failed !!!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HLOGE("PerfRecordSwitchCpuWide retren failed !!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PerfRecordSwitchCpuWide::GetBinary(std::vector<uint8_t> &buf) const
|
bool PerfRecordSwitchCpuWide::GetBinary(std::vector<uint8_t> &buf) const
|
||||||
{
|
{
|
||||||
if (buf.size() < GetSize()) {
|
if (buf.size() < GetSize()) {
|
||||||
@ -1244,6 +1041,23 @@ pid_t PerfRecordSample::GetServerPidof(unsigned int ipNr)
|
|||||||
return serverPidMap_[ipNr];
|
return serverPidMap_[ipNr];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PerfEventRecord& PerfEventRecordFactory::GetPerfEventRecord(PerfRecordType type, uint8_t* data,
|
||||||
|
const perf_event_attr &attr)
|
||||||
|
{
|
||||||
|
HLOG_ASSERT(data != nullptr);
|
||||||
|
PerfEventRecord* record = nullptr;
|
||||||
|
auto it = recordMap_.find(type);
|
||||||
|
if (it == recordMap_.end()) {
|
||||||
|
record = CreatePerfEventRecord(type);
|
||||||
|
recordMap_.emplace(type, record);
|
||||||
|
} else {
|
||||||
|
record = it->second;
|
||||||
|
}
|
||||||
|
record->Init(data, attr);
|
||||||
|
return *record;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HiPerf
|
} // namespace HiPerf
|
||||||
} // namespace Developtools
|
} // namespace Developtools
|
||||||
} // namespace OHOS
|
} // namespace OHOS
|
||||||
|
@ -117,16 +117,16 @@ void PerfEvents::ReadRecordsFromSpeMmaps(MmapFd& mmapFd, u64 auxOffset, u64 auxS
|
|||||||
arm_spe_reference(), cpu, tid, cpu, pid);
|
arm_spe_reference(), cpu, tid, cpu, pid);
|
||||||
static std::vector<u8> vbuf(RECORD_SIZE_LIMIT);
|
static std::vector<u8> vbuf(RECORD_SIZE_LIMIT);
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
if ((buf = recordBuf_->AllocForWrite(auxtraceRecord.header.size + auxSize)) == nullptr) {
|
if ((buf = recordBuf_->AllocForWrite(auxtraceRecord.header_.size + auxSize)) == nullptr) {
|
||||||
HLOGD("alloc buffer failed: PerfRecordAuxtrace record, readSize: %llu", auxSize);
|
HLOGD("alloc buffer failed: PerfRecordAuxtrace record, readSize: %llu", auxSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auxtraceRecord.GetBinary1(vbuf);
|
auxtraceRecord.GetBinary1(vbuf);
|
||||||
if (memcpy_s(buf, auxtraceRecord.header.size, vbuf.data(), auxtraceRecord.header.size) != 0) {
|
if (memcpy_s(buf, auxtraceRecord.header_.size, vbuf.data(), auxtraceRecord.header_.size) != 0) {
|
||||||
HLOGE("memcpy_s return failed");
|
HLOGE("memcpy_s return failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buf += auxtraceRecord.header.size;
|
buf += auxtraceRecord.header_.size;
|
||||||
|
|
||||||
while (auxSize > 0) {
|
while (auxSize > 0) {
|
||||||
u64 readSize = pageSize_;
|
u64 readSize = pageSize_;
|
||||||
@ -1624,7 +1624,7 @@ void PerfEvents::ReadRecordFromBuf()
|
|||||||
const auto readingStartTime_ = steady_clock::now();
|
const auto readingStartTime_ = steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
#if !HIDEBUG_SKIP_CALLBACK
|
#if !HIDEBUG_SKIP_CALLBACK
|
||||||
recordCallBack_(GetPerfSampleFromCache(*type, p, *attr));
|
recordCallBack_(PerfEventRecordFactory::GetPerfEventRecord(*type, p, *attr));
|
||||||
#endif
|
#endif
|
||||||
recordEventCount_++;
|
recordEventCount_++;
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
@ -1643,7 +1643,7 @@ void PerfEvents::ReadRecordFromBuf()
|
|||||||
const auto readingStartTime_ = steady_clock::now();
|
const auto readingStartTime_ = steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
#if !HIDEBUG_SKIP_CALLBACK
|
#if !HIDEBUG_SKIP_CALLBACK
|
||||||
recordCallBack_(GetPerfSampleFromCache(*type, p, *attr));
|
recordCallBack_(PerfEventRecordFactory::GetPerfEventRecord(*type, p, *attr));
|
||||||
#endif
|
#endif
|
||||||
recordEventCount_++;
|
recordEventCount_++;
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
|
@ -278,20 +278,20 @@ bool PerfFileReader::ReadRecord(ProcessRecordCB &callback)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t *data = buf;
|
uint8_t *data = buf;
|
||||||
std::unique_ptr<PerfEventRecord> record = GetPerfEventRecord(
|
PerfEventRecord& record = PerfEventRecordFactory::GetPerfEventRecord(
|
||||||
static_cast<perf_event_type>(header->type), data, *attr);
|
static_cast<perf_event_type>(header->type), data, *attr);
|
||||||
// unknown record , break the process
|
// unknown record , break the process
|
||||||
if (!record) {
|
if (record.GetName() == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
HLOGV("record type %u", record->GetType());
|
HLOGV("record type %u", record.GetType());
|
||||||
}
|
}
|
||||||
remainingSize = remainingSize - header->size - speSize;
|
remainingSize = remainingSize - header->size - speSize;
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
const auto startCallbackTime = steady_clock::now();
|
const auto startCallbackTime = steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
// call callback to process, then destroy record
|
// call callback to process, then destroy record
|
||||||
callback(std::move(record));
|
callback(record);
|
||||||
recordNumber++;
|
recordNumber++;
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
readCallbackTime_ +=
|
readCallbackTime_ +=
|
||||||
@ -425,7 +425,7 @@ bool PerfFileReader::ReadFeatureSection()
|
|||||||
} else if (feature == FEATURE::HIPERF_FILES_UNISTACK_TABLE) {
|
} else if (feature == FEATURE::HIPERF_FILES_UNISTACK_TABLE) {
|
||||||
perfFileSections_.emplace_back(
|
perfFileSections_.emplace_back(
|
||||||
std::make_unique<PerfFileSectionUniStackTable>(feature, (char *)&buf[0], buf.size()));
|
std::make_unique<PerfFileSectionUniStackTable>(feature, (char *)&buf[0], buf.size()));
|
||||||
PerfRecordSample::dumpRemoveStack_ = true;
|
PerfRecordSample::SetDumpRemoveStack(true);
|
||||||
} else {
|
} else {
|
||||||
HLOGW("still not imp how to process with feature %d", feature);
|
HLOGW("still not imp how to process with feature %d", feature);
|
||||||
}
|
}
|
||||||
|
@ -125,10 +125,10 @@ bool PerfFileWriter::WriteRecord(const PerfEventRecord &record)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLOGV("write '%s', size %zu", record.GetName().c_str(), record.GetSize());
|
HLOGV("write '%s', size %zu", record.GetName(), record.GetSize());
|
||||||
|
|
||||||
CHECK_TRUE(record.GetSize() > RECORD_SIZE_LIMIT_SPE, false, 1,
|
CHECK_TRUE(record.GetSize() > RECORD_SIZE_LIMIT_SPE, false, 1,
|
||||||
"%s record size exceed limit", record.GetName().c_str());
|
"%s record size exceed limit", record.GetName());
|
||||||
// signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0xb64eb195
|
// signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0xb64eb195
|
||||||
static std::vector<u8> buf(RECORD_SIZE_LIMIT_SPE);
|
static std::vector<u8> buf(RECORD_SIZE_LIMIT_SPE);
|
||||||
|
|
||||||
@ -186,13 +186,13 @@ bool PerfFileWriter::ReadRecords(ProcessRecordCB &callback)
|
|||||||
}
|
}
|
||||||
uint8_t *data = buf;
|
uint8_t *data = buf;
|
||||||
// the record is allowed from a cache memory, does not free memory after use
|
// the record is allowed from a cache memory, does not free memory after use
|
||||||
auto record = GetPerfSampleFromCacheMain(static_cast<perf_event_type>(header->type),
|
PerfEventRecord& record = PerfEventRecordFactory::GetPerfEventRecord(
|
||||||
data, defaultEventAttr_);
|
static_cast<perf_event_type>(header->type), data, defaultEventAttr_);
|
||||||
// skip unknown record
|
// skip unknown record
|
||||||
CHECK_TRUE(record == nullptr, true, 0, "");
|
CHECK_TRUE(record.GetName() == nullptr, true, 0, "");
|
||||||
remainingSize = remainingSize - header->size - speSize;
|
remainingSize = remainingSize - header->size - speSize;
|
||||||
// call callback to process, do not destroy the record
|
// call callback to process, do not destroy the record
|
||||||
callback(std::move(record));
|
callback(record);
|
||||||
recordNumber++;
|
recordNumber++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -405,13 +405,13 @@ void SubCommandDump::ExprotUserStack(const PerfRecordSample &recordSample)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubCommandDump::ExprotUserData(std::unique_ptr<PerfEventRecord> &record)
|
void SubCommandDump::ExprotUserData(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
if (currectSampleIndex_++ != exportSampleIndex_) {
|
if (currectSampleIndex_++ != exportSampleIndex_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PerfRecordSample *recordSample = static_cast<PerfRecordSample *>(record.get());
|
PerfRecordSample* recordSample = static_cast<PerfRecordSample*>(&record);
|
||||||
ExprotUserStack(*recordSample);
|
ExprotUserStack(*recordSample);
|
||||||
|
|
||||||
std::string userData =
|
std::string userData =
|
||||||
@ -427,14 +427,14 @@ void SubCommandDump::ExprotUserData(std::unique_ptr<PerfEventRecord> &record)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubCommandDump::DumpCallChain(int indent, std::unique_ptr<PerfRecordSample> &sample)
|
void SubCommandDump::DumpCallChain(int indent, const PerfRecordSample& sample)
|
||||||
{
|
{
|
||||||
PRINT_INDENT(indent, "\n callchain: %zu\n", sample->callFrames_.size());
|
PRINT_INDENT(indent, "\n callchain: %zu\n", sample.callFrames_.size());
|
||||||
if (sample->callFrames_.size() > 0) {
|
if (sample.callFrames_.size() > 0) {
|
||||||
indent += indent + 1;
|
indent += indent + 1;
|
||||||
for (auto frameIt = sample->callFrames_.begin(); frameIt != sample->callFrames_.end();
|
for (auto frameIt = sample.callFrames_.begin(); frameIt != sample.callFrames_.end();
|
||||||
frameIt++) {
|
frameIt++) {
|
||||||
PRINT_INDENT(indent, "%02zd:%s\n", std::distance(frameIt, sample->callFrames_.end()),
|
PRINT_INDENT(indent, "%02zd:%s\n", std::distance(frameIt, sample.callFrames_.end()),
|
||||||
frameIt->ToSymbolString().c_str());
|
frameIt->ToSymbolString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,8 +443,8 @@ void SubCommandDump::DumpCallChain(int indent, std::unique_ptr<PerfRecordSample>
|
|||||||
void SubCommandDump::DumpDataPortion(int indent)
|
void SubCommandDump::DumpDataPortion(int indent)
|
||||||
{
|
{
|
||||||
int recordCount = 0;
|
int recordCount = 0;
|
||||||
auto recordcCallback = [&](std::unique_ptr<PerfEventRecord> record) {
|
auto recordcCallback = [&](PerfEventRecord& record) {
|
||||||
CHECK_TRUE(record == nullptr, false, 0, ""); // return false in callback can stop the read process
|
CHECK_TRUE(record.GetName() == nullptr, false, 0, ""); // return false in callback can stop the read process
|
||||||
|
|
||||||
// for UT
|
// for UT
|
||||||
if (exportSampleIndex_ > 0) {
|
if (exportSampleIndex_ > 0) {
|
||||||
@ -452,15 +452,13 @@ void SubCommandDump::DumpDataPortion(int indent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tell process tree what happend for rebuild symbols
|
// tell process tree what happend for rebuild symbols
|
||||||
vr_.UpdateFromRecord(*record);
|
vr_.UpdateFromRecord(record);
|
||||||
|
|
||||||
recordCount++;
|
recordCount++;
|
||||||
record->Dump(indent, outputFilename_, g_outputDump);
|
record.Dump(indent, outputFilename_, g_outputDump);
|
||||||
|
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
std::unique_ptr<PerfRecordSample> sample(
|
DumpCallChain(indent, static_cast<PerfRecordSample&>(record));
|
||||||
static_cast<PerfRecordSample *>(record.release()));
|
|
||||||
DumpCallChain(indent, sample);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -811,8 +811,8 @@ void SubCommandRecord::RecoverSavedCmdlinesSize()
|
|||||||
bool SubCommandRecord::PreparePerfEvent()
|
bool SubCommandRecord::PreparePerfEvent()
|
||||||
{
|
{
|
||||||
// we need to notify perfEvents_ sampling mode by SetRecordCallBack first
|
// we need to notify perfEvents_ sampling mode by SetRecordCallBack first
|
||||||
auto processRecord = [this](std::unique_ptr<PerfEventRecord> record) -> bool {
|
auto processRecord = [this](PerfEventRecord& record) -> bool {
|
||||||
return this->ProcessRecord(std::move(record));
|
return this->ProcessRecord(record);
|
||||||
};
|
};
|
||||||
perfEvents_.SetRecordCallBack(processRecord);
|
perfEvents_.SetRecordCallBack(processRecord);
|
||||||
|
|
||||||
@ -897,8 +897,8 @@ bool SubCommandRecord::PrepareSysKernel()
|
|||||||
|
|
||||||
bool SubCommandRecord::PrepareVirtualRuntime()
|
bool SubCommandRecord::PrepareVirtualRuntime()
|
||||||
{
|
{
|
||||||
auto saveRecord = [this](std::unique_ptr<PerfEventRecord> record) -> bool {
|
auto saveRecord = [this](PerfEventRecord& record) -> bool {
|
||||||
return this->SaveRecord(std::move(record), false);
|
return this->SaveRecord(record, false);
|
||||||
};
|
};
|
||||||
virtualRuntime_.SetRecordMode(saveRecord);
|
virtualRuntime_.SetRecordMode(saveRecord);
|
||||||
|
|
||||||
@ -1323,21 +1323,17 @@ void SubCommandRecord::RemoveVdsoTmpFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubCommandRecord::ProcessRecord(std::unique_ptr<PerfEventRecord> record)
|
bool SubCommandRecord::ProcessRecord(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
CHECK_TRUE(record == nullptr, false, 1, "record is null");
|
CHECK_TRUE(record.GetName() == nullptr, false, 1, "record is null");
|
||||||
#if HIDEBUG_RECORD_NOT_PROCESS
|
#if HIDEBUG_RECORD_NOT_PROCESS
|
||||||
// some times we want to check performance
|
// some times we want to check performance
|
||||||
// but we still want to see the record number
|
// but we still want to see the record number
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
recordSamples_++;
|
recordSamples_++;
|
||||||
} else {
|
} else {
|
||||||
recordNoSamples_++;
|
recordNoSamples_++;
|
||||||
}
|
}
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
|
||||||
// when the record is allowed from a cache memory, does not free memory after use
|
|
||||||
record.release();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
@ -1345,11 +1341,7 @@ bool SubCommandRecord::ProcessRecord(std::unique_ptr<PerfEventRecord> record)
|
|||||||
#endif
|
#endif
|
||||||
if (excludeHiperf_) {
|
if (excludeHiperf_) {
|
||||||
static pid_t pid = getpid();
|
static pid_t pid = getpid();
|
||||||
if (record->GetPid() == pid) {
|
if (record.GetPid() == pid) {
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
|
||||||
// when the record is allowed from a cache memory, does not free memory after use
|
|
||||||
record.release();
|
|
||||||
}
|
|
||||||
// discard record
|
// discard record
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1358,23 +1350,17 @@ bool SubCommandRecord::ProcessRecord(std::unique_ptr<PerfEventRecord> record)
|
|||||||
// May create some simulated events
|
// May create some simulated events
|
||||||
// it will call ProcessRecord before next line
|
// it will call ProcessRecord before next line
|
||||||
#if !HIDEBUG_RECORD_NOT_PROCESS_VM
|
#if !HIDEBUG_RECORD_NOT_PROCESS_VM
|
||||||
virtualRuntime_.UpdateFromRecord(*record);
|
virtualRuntime_.UpdateFromRecord(record);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
prcessRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
|
prcessRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
|
||||||
#endif
|
#endif
|
||||||
return SaveRecord(std::move(record), true);
|
return SaveRecord(record, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubCommandRecord::SaveRecord(std::unique_ptr<PerfEventRecord> record, bool ptrReleaseFlag)
|
bool SubCommandRecord::SaveRecord(const PerfEventRecord& record, bool ptrReleaseFlag)
|
||||||
{
|
{
|
||||||
ON_SCOPE_EXIT {
|
|
||||||
if (ptrReleaseFlag && record->GetType() == PERF_RECORD_SAMPLE) {
|
|
||||||
// when the record is allowed from a cache memory, does not free memory after use
|
|
||||||
record.release();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#if HIDEBUG_RECORD_NOT_SAVE
|
#if HIDEBUG_RECORD_NOT_SAVE
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -1389,22 +1375,22 @@ bool SubCommandRecord::SaveRecord(std::unique_ptr<PerfEventRecord> record, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record) {
|
if (record.GetName() != nullptr) {
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
const auto saveTime = steady_clock::now();
|
const auto saveTime = steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
if (!fileWriter_->WriteRecord(*record)) {
|
if (!fileWriter_->WriteRecord(record)) {
|
||||||
// write file failed, need stop record
|
// write file failed, need stop record
|
||||||
perfEvents_.StopTracking();
|
perfEvents_.StopTracking();
|
||||||
HLOGV("fail to write record %s", record->GetName().c_str());
|
HLOGV("fail to write record %s", record.GetName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
recordSamples_++;
|
recordSamples_++;
|
||||||
} else {
|
} else {
|
||||||
recordNoSamples_++;
|
recordNoSamples_++;
|
||||||
}
|
}
|
||||||
HLOGV(" write done. size=%zu name=%s", record->GetSize(), record->GetName().c_str());
|
HLOGV(" write done. size=%zu name=%s", record.GetSize(), record.GetName());
|
||||||
#ifdef HIPERF_DEBUG_TIME
|
#ifdef HIPERF_DEBUG_TIME
|
||||||
saveRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - saveTime);
|
saveRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - saveTime);
|
||||||
#endif
|
#endif
|
||||||
@ -1620,15 +1606,15 @@ bool SubCommandRecord::PostProcessRecordFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. read out the file and unwind
|
// 2. read out the file and unwind
|
||||||
auto record_callback = [&](std::unique_ptr<PerfEventRecord> record) {
|
auto record_callback = [&](PerfEventRecord& record) {
|
||||||
if (record == nullptr) {
|
if (record.GetName() == nullptr) {
|
||||||
// return false in callback can stop the read process
|
// return false in callback can stop the read process
|
||||||
return false;
|
return false;
|
||||||
} else if (record->GetType() == PERF_RECORD_SAMPLE) {
|
} else if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
HLOGM("readback record for unwind");
|
HLOGM("readback record for unwind");
|
||||||
virtualRuntime_.UnwindFromRecord(static_cast<PerfRecordSample &>(*record));
|
virtualRuntime_.UnwindFromRecord(static_cast<PerfRecordSample&>(record));
|
||||||
}
|
}
|
||||||
SaveRecord(std::move(record));
|
SaveRecord(record);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
fileReader->ReadDataSection(record_callback);
|
fileReader->ReadDataSection(record_callback);
|
||||||
@ -1669,22 +1655,20 @@ void SubCommandRecord::SymbolicHits()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
bool SubCommandRecord::CollectionSymbol(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
CHECK_TRUE(record == nullptr, false, 0, "");
|
CHECK_TRUE(record.GetName() == nullptr, false, 0, "");
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
PerfRecordSample *sample = static_cast<PerfRecordSample *>(record.get());
|
PerfRecordSample* sample = static_cast<PerfRecordSample*>(&record);
|
||||||
#if USE_COLLECT_SYMBOLIC
|
#if USE_COLLECT_SYMBOLIC
|
||||||
CollectSymbol(sample);
|
CollectSymbol(sample);
|
||||||
#else
|
#else
|
||||||
virtualRuntime_.SymbolicRecord(*sample);
|
virtualRuntime_.SymbolicRecord(*sample);
|
||||||
#endif
|
#endif
|
||||||
// the record is allowed from a cache memory, does not free memory after use
|
|
||||||
record.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSpe_ && record->GetType() == PERF_RECORD_AUXTRACE) {
|
if (isSpe_ && record.GetType() == PERF_RECORD_AUXTRACE) {
|
||||||
PerfRecordAuxtrace *sample = static_cast<PerfRecordAuxtrace *>(record.get());
|
PerfRecordAuxtrace* sample = static_cast<PerfRecordAuxtrace*>(&record);
|
||||||
virtualRuntime_.SymbolSpeRecord(*sample);
|
virtualRuntime_.SymbolSpeRecord(*sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1694,7 +1678,7 @@ bool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
|
|||||||
void SubCommandRecord::CollectSymbol(PerfRecordSample *sample)
|
void SubCommandRecord::CollectSymbol(PerfRecordSample *sample)
|
||||||
{
|
{
|
||||||
CHECK_TRUE(sample == nullptr, NO_RETVAL, 0, "");
|
CHECK_TRUE(sample == nullptr, NO_RETVAL, 0, "");
|
||||||
perf_callchain_context context = sample->inKernel() ? PERF_CONTEXT_KERNEL
|
perf_callchain_context context = sample->InKernel() ? PERF_CONTEXT_KERNEL
|
||||||
: PERF_CONTEXT_USER;
|
: PERF_CONTEXT_USER;
|
||||||
pid_t serverPid;
|
pid_t serverPid;
|
||||||
// if no nr use ip ? remove stack nr == 0?
|
// if no nr use ip ? remove stack nr == 0?
|
||||||
@ -1754,8 +1738,8 @@ bool SubCommandRecord::FinishWriteRecordFile()
|
|||||||
virtualRuntime_.CollectDedupSymbol(kernelSymbolsHits_, userSymbolsHits_);
|
virtualRuntime_.CollectDedupSymbol(kernelSymbolsHits_, userSymbolsHits_);
|
||||||
} else {
|
} else {
|
||||||
fileWriter_->ReadDataSection(
|
fileWriter_->ReadDataSection(
|
||||||
[this] (std::unique_ptr<PerfEventRecord> record) -> bool {
|
[this] (PerfEventRecord& record) -> bool {
|
||||||
return this->CollectionSymbol(std::move(record));
|
return this->CollectionSymbol(record);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#if USE_COLLECT_SYMBOLIC
|
#if USE_COLLECT_SYMBOLIC
|
||||||
|
@ -223,13 +223,14 @@ void SubCommandReport::ProcessSample(std::unique_ptr<PerfRecordSample> &sample)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubCommandReport::RecordCallBack(std::unique_ptr<PerfEventRecord> record)
|
bool SubCommandReport::RecordCallBack(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
// tell process tree what happend for rebuild symbols
|
// tell process tree what happend for rebuild symbols
|
||||||
GetReport().virtualRuntime_.UpdateFromRecord(*record);
|
GetReport().virtualRuntime_.UpdateFromRecord(record);
|
||||||
|
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
if (record.GetType() == PERF_RECORD_SAMPLE) {
|
||||||
std::unique_ptr<PerfRecordSample> sample(static_cast<PerfRecordSample *>(record.release()));
|
std::unique_ptr<PerfRecordSample> sample
|
||||||
|
= std::make_unique<PerfRecordSample>(static_cast<PerfRecordSample&>(record));
|
||||||
std::unique_ptr<PerfRecordSample> prevSample = nullptr;
|
std::unique_ptr<PerfRecordSample> prevSample = nullptr;
|
||||||
if (cpuOffMode_) {
|
if (cpuOffMode_) {
|
||||||
auto prevIt = prevSampleCache_.find(sample->data_.tid);
|
auto prevIt = prevSampleCache_.find(sample->data_.tid);
|
||||||
@ -264,7 +265,7 @@ bool SubCommandReport::RecordCallBack(std::unique_ptr<PerfEventRecord> record)
|
|||||||
} else {
|
} else {
|
||||||
#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF
|
#if defined(HAVE_PROTOBUF) && HAVE_PROTOBUF
|
||||||
if (protobufFormat_) {
|
if (protobufFormat_) {
|
||||||
protobufOutputFileWriter_->ProcessRecord(*record);
|
protobufOutputFileWriter_->ProcessRecord(record);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -478,8 +479,8 @@ bool SubCommandReport::LoadPerfData()
|
|||||||
// before load data section
|
// before load data section
|
||||||
SetHM();
|
SetHM();
|
||||||
recordFileReader_->ReadDataSection(
|
recordFileReader_->ReadDataSection(
|
||||||
[this] (std::unique_ptr<PerfEventRecord> record) -> bool {
|
[this] (PerfEventRecord& record) -> bool {
|
||||||
return this->RecordCallBack(std::move(record));
|
return this->RecordCallBack(record);
|
||||||
});
|
});
|
||||||
if (cpuOffMode_) {
|
if (cpuOffMode_) {
|
||||||
FlushCacheRecord();
|
FlushCacheRecord();
|
||||||
|
@ -148,7 +148,7 @@ VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid, const std::str
|
|||||||
thread.name_.c_str(), thread.GetMaps().size());
|
thread.name_.c_str(), thread.GetMaps().size());
|
||||||
// we need make a PerfRecordComm
|
// we need make a PerfRecordComm
|
||||||
auto commRecord = std::make_unique<PerfRecordComm>(IsKernelThread(pid), pid, tid, thread.name_);
|
auto commRecord = std::make_unique<PerfRecordComm>(IsKernelThread(pid), pid, tid, thread.name_);
|
||||||
recordCallBack_(std::move(commRecord));
|
recordCallBack_(*commRecord);
|
||||||
// only work for pid
|
// only work for pid
|
||||||
if (pid == tid) {
|
if (pid == tid) {
|
||||||
if (isHM_) {
|
if (isHM_) {
|
||||||
@ -169,7 +169,7 @@ VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid, const std::str
|
|||||||
HLOGD("make PerfRecordMmap2 %d:%d:%s:%s(0x%" PRIx64 "-0x%" PRIx64 ")@%" PRIx64 " ",
|
HLOGD("make PerfRecordMmap2 %d:%d:%s:%s(0x%" PRIx64 "-0x%" PRIx64 ")@%" PRIx64 " ",
|
||||||
thread.pid_, thread.tid_, thread.name_.c_str(), map->name.c_str(),
|
thread.pid_, thread.tid_, thread.name_.c_str(), map->name.c_str(),
|
||||||
map->begin, map->end, map->offset);
|
map->begin, map->end, map->offset);
|
||||||
recordCallBack_(std::move(mmapRecord));
|
recordCallBack_(*mmapRecord);
|
||||||
if (updateNormalSymbol) {
|
if (updateNormalSymbol) {
|
||||||
UpdateSymbols(map, pid);
|
UpdateSymbols(map, pid);
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ void VirtualRuntime::UpdateKernelModulesSpaceMaps()
|
|||||||
for (const auto &map : koMaps) {
|
for (const auto &map : koMaps) {
|
||||||
auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin,
|
auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin,
|
||||||
map.end - map.begin, 0, map.name);
|
map.end - map.begin, 0, map.name);
|
||||||
recordCallBack_(std::move(record));
|
recordCallBack_(*record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::move(koMaps.begin(), koMaps.end(), std::back_inserter(kernelSpaceMemMaps_));
|
std::move(koMaps.begin(), koMaps.end(), std::back_inserter(kernelSpaceMemMaps_));
|
||||||
@ -299,7 +299,7 @@ void VirtualRuntime::UpdateKernelSpaceMaps()
|
|||||||
if (recordCallBack_) {
|
if (recordCallBack_) {
|
||||||
auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin,
|
auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin,
|
||||||
map.end - map.begin, 0, map.name);
|
map.end - map.begin, 0, map.name);
|
||||||
recordCallBack_(std::move(record));
|
recordCallBack_(*record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ void VirtualRuntime::UpdateKernelSymbols()
|
|||||||
kernelFile->textExecVaddrFileOffset_, KERNEL_MMAP_NAME);
|
kernelFile->textExecVaddrFileOffset_, KERNEL_MMAP_NAME);
|
||||||
|
|
||||||
if (recordCallBack_) {
|
if (recordCallBack_) {
|
||||||
recordCallBack_(std::move(record));
|
recordCallBack_(*record);
|
||||||
}
|
}
|
||||||
symbolsFiles_.emplace_back(std::move(kernelFile));
|
symbolsFiles_.emplace_back(std::move(kernelFile));
|
||||||
} else {
|
} else {
|
||||||
@ -395,7 +395,7 @@ void VirtualRuntime::DedupFromRecord(PerfRecordSample *recordSample)
|
|||||||
}
|
}
|
||||||
// callstack dedup success
|
// callstack dedup success
|
||||||
recordSample->stackId_.value = stackId.value;
|
recordSample->stackId_.value = stackId.value;
|
||||||
recordSample->header.size -= (sizeof(u64) * nr - sizeof(stackId));
|
recordSample->header_.size -= (sizeof(u64) * nr - sizeof(stackId));
|
||||||
recordSample->data_.nr = 0;
|
recordSample->data_.nr = 0;
|
||||||
recordSample->data_.ips = nullptr;
|
recordSample->data_.ips = nullptr;
|
||||||
recordSample->removeStack_ = true;
|
recordSample->removeStack_ = true;
|
||||||
@ -558,7 +558,7 @@ void VirtualRuntime::NeedDropKernelCallChain(PerfRecordSample &sample)
|
|||||||
{
|
{
|
||||||
// only do this in record mode.
|
// only do this in record mode.
|
||||||
if (recordCallBack_ == nullptr || needkernelCallChain_ ||
|
if (recordCallBack_ == nullptr || needkernelCallChain_ ||
|
||||||
!sample.inKernel() || sample.data_.nr == 0) {
|
!sample.InKernel() || sample.data_.nr == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,11 +575,11 @@ void VirtualRuntime::NeedDropKernelCallChain(PerfRecordSample &sample)
|
|||||||
}
|
}
|
||||||
sample.skipKernel_ = skip;
|
sample.skipKernel_ = skip;
|
||||||
sample.data_.nr -= skip;
|
sample.data_.nr -= skip;
|
||||||
sample.header.size -= sizeof(u64) * skip;
|
sample.header_.size -= sizeof(u64) * skip;
|
||||||
if (sample.data_.server_nr > 0) {
|
if (sample.data_.server_nr > 0) {
|
||||||
sample.skipPid_ = skipPid;
|
sample.skipPid_ = skipPid;
|
||||||
sample.data_.server_nr -= skipPid;
|
sample.data_.server_nr -= skipPid;
|
||||||
sample.header.size -= sizeof(u64) * skipPid;
|
sample.header_.size -= sizeof(u64) * skipPid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,9 +661,9 @@ void VirtualRuntime::UpdateFromRecord(PerfRecordSample &recordSample)
|
|||||||
|
|
||||||
void VirtualRuntime::UpdateFromRecord(PerfRecordMmap &recordMmap)
|
void VirtualRuntime::UpdateFromRecord(PerfRecordMmap &recordMmap)
|
||||||
{
|
{
|
||||||
HLOGV(" MMAP: size %d pid %u tid %u", recordMmap.header.size, recordMmap.data_.pid,
|
HLOGV(" MMAP: size %d pid %u tid %u", recordMmap.header_.size, recordMmap.data_.pid,
|
||||||
recordMmap.data_.tid);
|
recordMmap.data_.tid);
|
||||||
HLOGV(" MMAP: %s dso '%s' (0x%llx-0x%llx)@0x%llx", recordMmap.inKernel() ? "kernel" : "user",
|
HLOGV(" MMAP: %s dso '%s' (0x%llx-0x%llx)@0x%llx", recordMmap.InKernel() ? "kernel" : "user",
|
||||||
recordMmap.data_.filename, recordMmap.data_.addr,
|
recordMmap.data_.filename, recordMmap.data_.addr,
|
||||||
recordMmap.data_.addr + recordMmap.data_.len, recordMmap.data_.pgoff);
|
recordMmap.data_.addr + recordMmap.data_.len, recordMmap.data_.pgoff);
|
||||||
// kernel mmap
|
// kernel mmap
|
||||||
@ -671,12 +671,12 @@ void VirtualRuntime::UpdateFromRecord(PerfRecordMmap &recordMmap)
|
|||||||
if (IsKernelThread(recordMmap.data_.pid)) {
|
if (IsKernelThread(recordMmap.data_.pid)) {
|
||||||
UpdateKernelThreadMap(recordMmap.data_.pid, recordMmap.data_.addr,
|
UpdateKernelThreadMap(recordMmap.data_.pid, recordMmap.data_.addr,
|
||||||
recordMmap.data_.len, recordMmap.data_.filename);
|
recordMmap.data_.len, recordMmap.data_.filename);
|
||||||
} else if (recordMmap.inKernel()) {
|
} else if (recordMmap.InKernel()) {
|
||||||
UpdatekernelMap(recordMmap.data_.addr, recordMmap.data_.addr + recordMmap.data_.len,
|
UpdatekernelMap(recordMmap.data_.addr, recordMmap.data_.addr + recordMmap.data_.len,
|
||||||
recordMmap.data_.pgoff, recordMmap.data_.filename);
|
recordMmap.data_.pgoff, recordMmap.data_.filename);
|
||||||
} else {
|
} else {
|
||||||
NeedAdaptSandboxPath(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header.size);
|
NeedAdaptSandboxPath(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header_.size);
|
||||||
FixHMBundleMmap(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header.size);
|
FixHMBundleMmap(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header_.size);
|
||||||
auto map = UpdateThreadMaps(recordMmap.data_.pid, recordMmap.data_.tid, recordMmap.data_.filename,
|
auto map = UpdateThreadMaps(recordMmap.data_.pid, recordMmap.data_.tid, recordMmap.data_.filename,
|
||||||
recordMmap.data_.addr, recordMmap.data_.len, recordMmap.data_.pgoff);
|
recordMmap.data_.addr, recordMmap.data_.len, recordMmap.data_.pgoff);
|
||||||
UpdateSymbols(map, recordMmap.data_.pid);
|
UpdateSymbols(map, recordMmap.data_.pid);
|
||||||
@ -715,11 +715,11 @@ bool VirtualRuntime::CheckValidSandBoxMmap(PerfRecordMmap2 &recordMmap2)
|
|||||||
u64 len = elfLoadInfoMap[0].mmapLen;
|
u64 len = elfLoadInfoMap[0].mmapLen;
|
||||||
u64 pgoff = elfLoadInfoMap[0].offset & (~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0));
|
u64 pgoff = elfLoadInfoMap[0].offset & (~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0));
|
||||||
std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg =
|
std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg =
|
||||||
std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
std::make_unique<PerfRecordMmap2>(recordMmap2.InKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
||||||
begin, len, pgoff, 0, 0, 0, PROT_READ, 0, std::string(recordMmap2.data_.filename));
|
begin, len, pgoff, 0, 0, 0, PROT_READ, 0, std::string(recordMmap2.data_.filename));
|
||||||
UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, mmap2FirstSeg->data_.filename,
|
UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, mmap2FirstSeg->data_.filename,
|
||||||
mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff);
|
mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff);
|
||||||
recordCallBack_(std::move(mmap2FirstSeg));
|
recordCallBack_(*mmap2FirstSeg);
|
||||||
} else {
|
} else {
|
||||||
auto elfLoadInfoMap = symFile->GetPtLoads();
|
auto elfLoadInfoMap = symFile->GetPtLoads();
|
||||||
u64 begin = recordMmap2.data_.addr - elfLoadInfoMap[0].mmapLen;
|
u64 begin = recordMmap2.data_.addr - elfLoadInfoMap[0].mmapLen;
|
||||||
@ -727,21 +727,21 @@ bool VirtualRuntime::CheckValidSandBoxMmap(PerfRecordMmap2 &recordMmap2)
|
|||||||
u64 pgoff = elfLoadInfoMap[0].offset &
|
u64 pgoff = elfLoadInfoMap[0].offset &
|
||||||
(~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0));
|
(~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0));
|
||||||
std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg =
|
std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg =
|
||||||
std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
std::make_unique<PerfRecordMmap2>(recordMmap2.InKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
||||||
begin, len, pgoff, 0, 0, 0, PROT_READ, 0, curMap->name);
|
begin, len, pgoff, 0, 0, 0, PROT_READ, 0, curMap->name);
|
||||||
UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, curMap->name,
|
UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, curMap->name,
|
||||||
mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff);
|
mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff);
|
||||||
recordCallBack_(std::move(mmap2FirstSeg));
|
recordCallBack_(*mmap2FirstSeg);
|
||||||
|
|
||||||
std::unique_ptr<PerfRecordMmap2> mmap2SecondSegment =
|
std::unique_ptr<PerfRecordMmap2> mmap2SecondSegment =
|
||||||
std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
std::make_unique<PerfRecordMmap2>(recordMmap2.InKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid,
|
||||||
recordMmap2.data_.addr,
|
recordMmap2.data_.addr,
|
||||||
recordMmap2.data_.len,
|
recordMmap2.data_.len,
|
||||||
recordMmap2.data_.pgoff - prevMap->offset, // minus load offset of hap
|
recordMmap2.data_.pgoff - prevMap->offset, // minus load offset of hap
|
||||||
0, 0, 0, recordMmap2.data_.prot, 0, curMap->name);
|
0, 0, 0, recordMmap2.data_.prot, 0, curMap->name);
|
||||||
UpdateThreadMaps(mmap2SecondSegment->data_.pid, mmap2SecondSegment->data_.tid, curMap->name,
|
UpdateThreadMaps(mmap2SecondSegment->data_.pid, mmap2SecondSegment->data_.tid, curMap->name,
|
||||||
mmap2SecondSegment->data_.addr, mmap2SecondSegment->data_.len, mmap2SecondSegment->data_.pgoff);
|
mmap2SecondSegment->data_.addr, mmap2SecondSegment->data_.len, mmap2SecondSegment->data_.pgoff);
|
||||||
recordCallBack_(std::move(mmap2SecondSegment));
|
recordCallBack_(*mmap2SecondSegment);
|
||||||
recordMmap2.discard_ = true;
|
recordMmap2.discard_ = true;
|
||||||
}
|
}
|
||||||
symbolsFiles_.emplace_back(std::move(symFile));
|
symbolsFiles_.emplace_back(std::move(symFile));
|
||||||
@ -769,15 +769,15 @@ void VirtualRuntime::UpdateFromRecord(PerfRecordMmap2 &recordMmap2)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLOGV(" MMAP2: size %d pid %u tid %u", recordMmap2.header.size, recordMmap2.data_.pid,
|
HLOGV(" MMAP2: size %d pid %u tid %u", recordMmap2.header_.size, recordMmap2.data_.pid,
|
||||||
recordMmap2.data_.tid);
|
recordMmap2.data_.tid);
|
||||||
HLOGV(" MMAP2: %s dso '%s' (0x%llx-0x%llx)@0x%llx prot:%u", recordMmap2.inKernel() ? "kernel" : "user",
|
HLOGV(" MMAP2: %s dso '%s' (0x%llx-0x%llx)@0x%llx prot:%u", recordMmap2.InKernel() ? "kernel" : "user",
|
||||||
recordMmap2.data_.filename, recordMmap2.data_.addr,
|
recordMmap2.data_.filename, recordMmap2.data_.addr,
|
||||||
recordMmap2.data_.addr + recordMmap2.data_.len, recordMmap2.data_.pgoff, recordMmap2.data_.prot);
|
recordMmap2.data_.addr + recordMmap2.data_.len, recordMmap2.data_.pgoff, recordMmap2.data_.prot);
|
||||||
|
|
||||||
if (recordCallBack_) {
|
if (recordCallBack_) {
|
||||||
if (NeedAdaptSandboxPath(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header.size)) {
|
if (NeedAdaptSandboxPath(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header_.size)) {
|
||||||
FixHMBundleMmap(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header.size);
|
FixHMBundleMmap(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header_.size);
|
||||||
CHECK_TRUE(!CheckValidSandBoxMmap(recordMmap2), NO_RETVAL, 0, "");
|
CHECK_TRUE(!CheckValidSandBoxMmap(recordMmap2), NO_RETVAL, 0, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1258,7 +1258,7 @@ void VirtualRuntime::UpdateServiceSpaceMaps()
|
|||||||
std::make_unique<PerfRecordMmap>(true, SYSMGR_PID, SYSMGR_PID,
|
std::make_unique<PerfRecordMmap>(true, SYSMGR_PID, SYSMGR_PID,
|
||||||
map->begin, map->end - map->begin,
|
map->begin, map->end - map->begin,
|
||||||
0, SYSMGR_FILE_NAME);
|
0, SYSMGR_FILE_NAME);
|
||||||
recordCallBack_(std::move(record));
|
recordCallBack_(*record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1296,7 +1296,7 @@ void VirtualRuntime::UpdateDevhostSpaceMaps()
|
|||||||
std::make_unique<PerfRecordMmap>(false, devhostPid_, devhostPid_,
|
std::make_unique<PerfRecordMmap>(false, devhostPid_, devhostPid_,
|
||||||
map->begin, map->end - map->begin,
|
map->begin, map->end - map->begin,
|
||||||
0, map->name);
|
0, map->name);
|
||||||
recordCallBack_(std::move(record));
|
recordCallBack_(*record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ bool FuzzPerfFileReader(const uint8_t *data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader->ReadFeatureSection();
|
reader->ReadFeatureSection();
|
||||||
auto recordCallback = [&](const std::unique_ptr<PerfEventRecord> &record) {
|
auto recordCallback = [&](PerfEventRecord& record) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "perf_event_record_test.h"
|
#include "perf_event_record_test.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
using namespace testing::ext;
|
using namespace testing::ext;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -80,7 +81,8 @@ HWTEST_F(PerfEventRecordTest, Mmap, TestSize.Level1)
|
|||||||
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmapData) - KILO + strlen(data.filename) + 1;
|
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmapData) - KILO + strlen(data.filename) + 1;
|
||||||
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
||||||
|
|
||||||
PerfRecordMmap recordOut(buff.data());
|
PerfRecordMmap recordOut;
|
||||||
|
recordOut.Init(buff.data());
|
||||||
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP);
|
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP);
|
||||||
ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP);
|
ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP);
|
||||||
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -115,7 +117,8 @@ HWTEST_F(PerfEventRecordTest, Mmap2, TestSize.Level1)
|
|||||||
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmap2Data) - KILO + strlen(data.filename) + 1;
|
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmap2Data) - KILO + strlen(data.filename) + 1;
|
||||||
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
||||||
|
|
||||||
PerfRecordMmap2 recordOut(buff.data());
|
PerfRecordMmap2 recordOut;
|
||||||
|
recordOut.Init(buff.data());
|
||||||
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP2);
|
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP2);
|
||||||
ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP2);
|
ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP2);
|
||||||
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -153,7 +156,8 @@ HWTEST_F(PerfEventRecordTest, Comm, TestSize.Level1)
|
|||||||
|
|
||||||
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordCommData) - KILO + strlen(data.comm) + 1;
|
size_t buffSize = HEADER_SIZE + sizeof(PerfRecordCommData) - KILO + strlen(data.comm) + 1;
|
||||||
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
ASSERT_EQ(recordIn.GetSize(), buffSize);
|
||||||
PerfRecordComm recordOut(buff.data());
|
PerfRecordComm recordOut;
|
||||||
|
recordOut.Init(buff.data());
|
||||||
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_COMM);
|
ASSERT_EQ(recordOut.GetType(), PERF_RECORD_COMM);
|
||||||
ASSERT_EQ(recordOut.GetName(), RECORDNAME_COMM);
|
ASSERT_EQ(recordOut.GetName(), RECORDNAME_COMM);
|
||||||
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -175,7 +179,8 @@ HWTEST_F(PerfEventRecordTest, Lost, TestSize.Level1)
|
|||||||
{PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordLostst)},
|
{PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordLostst)},
|
||||||
{1, 2}};
|
{1, 2}};
|
||||||
|
|
||||||
PerfRecordLost record((uint8_t *)&data);
|
PerfRecordLost record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_LOST);
|
ASSERT_EQ(record.GetName(), RECORDNAME_LOST);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -197,7 +202,8 @@ HWTEST_F(PerfEventRecordTest, Exit, TestSize.Level1)
|
|||||||
TestRecordExitst data = {{PERF_RECORD_EXIT, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordExitst)},
|
TestRecordExitst data = {{PERF_RECORD_EXIT, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordExitst)},
|
||||||
{1, 2, 3, 4, 5}};
|
{1, 2, 3, 4, 5}};
|
||||||
|
|
||||||
PerfRecordExit record((uint8_t *)&data);
|
PerfRecordExit record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_EXIT);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_EXIT);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_EXIT);
|
ASSERT_EQ(record.GetName(), RECORDNAME_EXIT);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -220,7 +226,8 @@ HWTEST_F(PerfEventRecordTest, Throttle, TestSize.Level1)
|
|||||||
{PERF_RECORD_THROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordThrottlest)},
|
{PERF_RECORD_THROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordThrottlest)},
|
||||||
{1, 2, 3}};
|
{1, 2, 3}};
|
||||||
|
|
||||||
PerfRecordThrottle record((uint8_t *)&data);
|
PerfRecordThrottle record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_THROTTLE);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_THROTTLE);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_THROTTLE);
|
ASSERT_EQ(record.GetName(), RECORDNAME_THROTTLE);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -243,7 +250,8 @@ HWTEST_F(PerfEventRecordTest, Unthrottle, TestSize.Level1)
|
|||||||
{PERF_RECORD_UNTHROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordUNThrottlest)},
|
{PERF_RECORD_UNTHROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordUNThrottlest)},
|
||||||
{1, 2, 3}};
|
{1, 2, 3}};
|
||||||
|
|
||||||
PerfRecordUnthrottle record((uint8_t *)&data);
|
PerfRecordUnthrottle record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_UNTHROTTLE);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_UNTHROTTLE);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_UNTHROTTLE);
|
ASSERT_EQ(record.GetName(), RECORDNAME_UNTHROTTLE);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -265,7 +273,8 @@ HWTEST_F(PerfEventRecordTest, Fork, TestSize.Level1)
|
|||||||
TestRecordForkst data = {{PERF_RECORD_FORK, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordForkst)},
|
TestRecordForkst data = {{PERF_RECORD_FORK, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordForkst)},
|
||||||
{1, 2, 3, 4, 5}};
|
{1, 2, 3, 4, 5}};
|
||||||
|
|
||||||
PerfRecordFork record((uint8_t *)&data);
|
PerfRecordFork record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_FORK);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_FORK);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_FORK);
|
ASSERT_EQ(record.GetName(), RECORDNAME_FORK);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -419,7 +428,8 @@ HWTEST_F(PerfEventRecordTest, Sample, TestSize.Level1)
|
|||||||
{}};
|
{}};
|
||||||
InitTestRecordSample(data);
|
InitTestRecordSample(data);
|
||||||
|
|
||||||
PerfRecordSample record((uint8_t *)&data, attr);
|
PerfRecordSample record;
|
||||||
|
record.Init((uint8_t *)&data, attr);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_SAMPLE);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_SAMPLE);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_SAMPLE);
|
ASSERT_EQ(record.GetName(), RECORDNAME_SAMPLE);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -439,7 +449,8 @@ HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack1, TestSize.Level1)
|
|||||||
{}};
|
{}};
|
||||||
InitTestRecordSample(data);
|
InitTestRecordSample(data);
|
||||||
|
|
||||||
PerfRecordSample record((uint8_t *)&data, attr);
|
PerfRecordSample record;
|
||||||
|
record.Init((uint8_t *)&data, attr);
|
||||||
record.sampleType_ |= PERF_SAMPLE_REGS_USER;
|
record.sampleType_ |= PERF_SAMPLE_REGS_USER;
|
||||||
record.sampleType_ |= PERF_SAMPLE_STACK_USER;
|
record.sampleType_ |= PERF_SAMPLE_STACK_USER;
|
||||||
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
||||||
@ -472,7 +483,8 @@ HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack2, TestSize.Level1)
|
|||||||
{}};
|
{}};
|
||||||
InitTestRecordSample(data);
|
InitTestRecordSample(data);
|
||||||
|
|
||||||
PerfRecordSample record((uint8_t *)&data, attr);
|
PerfRecordSample record;
|
||||||
|
record.Init((uint8_t *)&data, attr);
|
||||||
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
||||||
|
|
||||||
std::vector<u64> ips = {};
|
std::vector<u64> ips = {};
|
||||||
@ -498,7 +510,8 @@ HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack3, TestSize.Level1)
|
|||||||
{}};
|
{}};
|
||||||
InitTestRecordSample(data);
|
InitTestRecordSample(data);
|
||||||
|
|
||||||
PerfRecordSample record((uint8_t *)&data, attr);
|
PerfRecordSample record;
|
||||||
|
record.Init((uint8_t *)&data, attr);
|
||||||
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
||||||
|
|
||||||
record.callFrames_ = {4, 5, 6, 7, 8, 9};
|
record.callFrames_ = {4, 5, 6, 7, 8, 9};
|
||||||
@ -527,7 +540,8 @@ HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack4, TestSize.Level1)
|
|||||||
{}};
|
{}};
|
||||||
InitTestRecordSample(data);
|
InitTestRecordSample(data);
|
||||||
|
|
||||||
PerfRecordSample record((uint8_t *)&data, attr);
|
PerfRecordSample record;
|
||||||
|
record.Init((uint8_t *)&data, attr);
|
||||||
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
|
||||||
|
|
||||||
record.callFrames_ = {};
|
record.callFrames_ = {};
|
||||||
@ -553,7 +567,8 @@ HWTEST_F(PerfEventRecordTest, Read, TestSize.Level1)
|
|||||||
PerfRecordReadst data = {{PERF_RECORD_READ, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordReadst)},
|
PerfRecordReadst data = {{PERF_RECORD_READ, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordReadst)},
|
||||||
{1, 2, {11, 12, 13, 14}}};
|
{1, 2, {11, 12, 13, 14}}};
|
||||||
|
|
||||||
PerfRecordRead record((uint8_t *)&data);
|
PerfRecordRead record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_READ);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_READ);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_READ);
|
ASSERT_EQ(record.GetName(), RECORDNAME_READ);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -575,7 +590,8 @@ HWTEST_F(PerfEventRecordTest, Aux, TestSize.Level1)
|
|||||||
PerfRecordAuxst data = {{PERF_RECORD_AUX, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordAuxst)},
|
PerfRecordAuxst data = {{PERF_RECORD_AUX, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordAuxst)},
|
||||||
{1, 2, 3}};
|
{1, 2, 3}};
|
||||||
|
|
||||||
PerfRecordAux record((uint8_t *)&data);
|
PerfRecordAux record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_AUX);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_AUX);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_AUX);
|
ASSERT_EQ(record.GetName(), RECORDNAME_AUX);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -598,7 +614,8 @@ HWTEST_F(PerfEventRecordTest, ItraceStart, TestSize.Level1)
|
|||||||
{PERF_RECORD_ITRACE_START, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordItraceStartst)},
|
{PERF_RECORD_ITRACE_START, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordItraceStartst)},
|
||||||
{1, 2}};
|
{1, 2}};
|
||||||
|
|
||||||
PerfRecordItraceStart record((uint8_t *)&data);
|
PerfRecordItraceStart record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_ITRACE_START);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_ITRACE_START);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_ITRACE_START);
|
ASSERT_EQ(record.GetName(), RECORDNAME_ITRACE_START);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -621,7 +638,8 @@ HWTEST_F(PerfEventRecordTest, LostSamples, TestSize.Level1)
|
|||||||
{PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordLostSamplesst)},
|
{PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordLostSamplesst)},
|
||||||
{1}};
|
{1}};
|
||||||
|
|
||||||
PerfRecordLostSamples record((uint8_t *)&data);
|
PerfRecordLostSamples record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_LOST_SAMPLES);
|
ASSERT_EQ(record.GetName(), RECORDNAME_LOST_SAMPLES);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -644,7 +662,8 @@ HWTEST_F(PerfEventRecordTest, Switch, TestSize.Level1)
|
|||||||
{PERF_RECORD_SWITCH, PERF_RECORD_MISC_KERNEL, sizeof(perf_event_header)},
|
{PERF_RECORD_SWITCH, PERF_RECORD_MISC_KERNEL, sizeof(perf_event_header)},
|
||||||
{}};
|
{}};
|
||||||
|
|
||||||
PerfRecordSwitch record((uint8_t *)&data);
|
PerfRecordSwitch record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH);
|
ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -667,7 +686,8 @@ HWTEST_F(PerfEventRecordTest, SwitchCpuWide, TestSize.Level1)
|
|||||||
{PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
|
{PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
|
||||||
{}};
|
{}};
|
||||||
|
|
||||||
PerfRecordSwitchCpuWide record((uint8_t *)&data);
|
PerfRecordSwitchCpuWide record;
|
||||||
|
record.Init((uint8_t *)&data);
|
||||||
ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH_CPU_WIDE);
|
ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH_CPU_WIDE);
|
||||||
ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH_CPU_WIDE);
|
ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH_CPU_WIDE);
|
||||||
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
|
||||||
@ -694,16 +714,84 @@ HWTEST_F(PerfEventRecordTest, GetPerfEventRecord, TestSize.Level1)
|
|||||||
if (type == PERF_RECORD_SAMPLE) {
|
if (type == PERF_RECORD_SAMPLE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::unique_ptr<PerfEventRecord> perfEventRecord =
|
PerfEventRecord& perfEventRecord =
|
||||||
GetPerfEventRecord(static_cast<perf_event_type>(type), reinterpret_cast<uint8_t *>(&data), attr);
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(type),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
if (type < PERF_RECORD_NAMESPACES) {
|
if (type < PERF_RECORD_NAMESPACES) {
|
||||||
ASSERT_EQ(perfEventRecord != nullptr, true);
|
ASSERT_EQ(perfEventRecord.GetName() != nullptr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::unique_ptr<PerfEventRecord> perfEventRecord =
|
PerfEventRecord& perfEventRecord =
|
||||||
GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
reinterpret_cast<uint8_t *>(&data), attr);
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
ASSERT_EQ(perfEventRecord != nullptr, true);
|
ASSERT_EQ(perfEventRecord.GetName() != nullptr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWTEST_F(PerfEventRecordTest, GetPerfEventRecord2, TestSize.Level1)
|
||||||
|
{
|
||||||
|
struct PerfRecordSwitchCpuWidest {
|
||||||
|
perf_event_header h;
|
||||||
|
PerfRecordSwitchCpuWideData d;
|
||||||
|
};
|
||||||
|
PerfRecordSwitchCpuWidest data = {
|
||||||
|
{PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
|
||||||
|
{}};
|
||||||
|
perf_event_attr attr {};
|
||||||
|
attr.sample_type = UINT64_MAX;
|
||||||
|
PerfEventRecord& perfEventRecord1 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
PerfEventRecord& perfEventRecord2 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
|
||||||
|
ASSERT_TRUE(&perfEventRecord1 == &perfEventRecord2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HWTEST_F(PerfEventRecordTest, GetPerfEventRecord3, TestSize.Level1)
|
||||||
|
{
|
||||||
|
struct PerfRecordSwitchCpuWidest {
|
||||||
|
perf_event_header h;
|
||||||
|
PerfRecordSwitchCpuWideData d;
|
||||||
|
};
|
||||||
|
PerfRecordSwitchCpuWidest data = {
|
||||||
|
{PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
|
||||||
|
{}};
|
||||||
|
perf_event_attr attr {};
|
||||||
|
attr.sample_type = UINT64_MAX;
|
||||||
|
PerfEventRecord& perfEventRecord1 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
PerfEventRecord& perfEventRecord2 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(INT32_MAX,
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
ASSERT_TRUE(perfEventRecord1.GetName() != nullptr);
|
||||||
|
ASSERT_TRUE(perfEventRecord2.GetName() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWTEST_F(PerfEventRecordTest, MultiThreadGetPerfEventRecord, TestSize.Level1)
|
||||||
|
{
|
||||||
|
struct PerfRecordSwitchCpuWidest {
|
||||||
|
perf_event_header h;
|
||||||
|
PerfRecordSwitchCpuWideData d;
|
||||||
|
};
|
||||||
|
PerfRecordSwitchCpuWidest data = {
|
||||||
|
{PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
|
||||||
|
{}};
|
||||||
|
perf_event_attr attr {};
|
||||||
|
attr.sample_type = UINT64_MAX;
|
||||||
|
PerfEventRecord& perfEventRecord1 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
|
||||||
|
std::thread t1([&perfEventRecord1, &data, attr]() {
|
||||||
|
PerfEventRecord& perfEventRecord2 =
|
||||||
|
PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
|
||||||
|
reinterpret_cast<uint8_t *>(&data), attr);
|
||||||
|
ASSERT_TRUE(&perfEventRecord1 != &perfEventRecord2);
|
||||||
|
});
|
||||||
|
t1.join();
|
||||||
}
|
}
|
||||||
} // namespace HiPerf
|
} // namespace HiPerf
|
||||||
} // namespace Developtools
|
} // namespace Developtools
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
static void TestCodeThread(void);
|
static void TestCodeThread(void);
|
||||||
static void RunTestThreads(std::vector<std::thread> &threads);
|
static void RunTestThreads(std::vector<std::thread> &threads);
|
||||||
static void SetAllConfig(PerfEvents &event);
|
static void SetAllConfig(PerfEvents &event);
|
||||||
static bool RecordCount(std::unique_ptr<PerfEventRecord> record);
|
static bool RecordCount(PerfEventRecord& record);
|
||||||
static void StatCount(
|
static void StatCount(
|
||||||
const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
|
const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
|
||||||
|
|
||||||
@ -71,13 +71,9 @@ void PerfEventsTest::TearDown() {}
|
|||||||
uint64_t PerfEventsTest::g_recordCount = 0;
|
uint64_t PerfEventsTest::g_recordCount = 0;
|
||||||
uint64_t PerfEventsTest::g_statCount = 0;
|
uint64_t PerfEventsTest::g_statCount = 0;
|
||||||
|
|
||||||
bool PerfEventsTest::RecordCount(std::unique_ptr<PerfEventRecord> record)
|
bool PerfEventsTest::RecordCount(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
g_recordCount++;
|
g_recordCount++;
|
||||||
if (record->GetType() == PERF_RECORD_SAMPLE) {
|
|
||||||
// the record is allowed from a cache memory, does not free memory after use
|
|
||||||
record.release();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ using namespace OHOS::HiviewDFX;
|
|||||||
namespace OHOS {
|
namespace OHOS {
|
||||||
namespace Developtools {
|
namespace Developtools {
|
||||||
namespace HiPerf {
|
namespace HiPerf {
|
||||||
using ProcessRecordCB = const std::function<bool(std::unique_ptr<PerfEventRecord> record)>;
|
using ProcessRecordCB = const std::function<bool(PerfEventRecord& record)>;
|
||||||
class PerfFileReaderTest : public testing::Test {
|
class PerfFileReaderTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
static void SetUpTestCase(void);
|
static void SetUpTestCase(void);
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
void LogLevelTest(std::vector<std::string> args, DebugLevel level);
|
void LogLevelTest(std::vector<std::string> args, DebugLevel level);
|
||||||
default_random_engine rnd_;
|
default_random_engine rnd_;
|
||||||
std::unique_ptr<VirtualRuntime> runtime_;
|
std::unique_ptr<VirtualRuntime> runtime_;
|
||||||
bool RecordCallBack(std::unique_ptr<PerfEventRecord> record);
|
bool RecordCallBack(PerfEventRecord& record);
|
||||||
size_t callbackCount_ = 0;
|
size_t callbackCount_ = 0;
|
||||||
|
|
||||||
void PrepareKernelSymbol();
|
void PrepareKernelSymbol();
|
||||||
@ -69,10 +69,10 @@ void VirtualRuntimeTest::TearDown()
|
|||||||
runtime_.release();
|
runtime_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtualRuntimeTest::RecordCallBack(std::unique_ptr<PerfEventRecord> record)
|
bool VirtualRuntimeTest::RecordCallBack(PerfEventRecord& record)
|
||||||
{
|
{
|
||||||
callbackCount_++;
|
callbackCount_++;
|
||||||
printf("callbackCount_ %zu: type %d\n", callbackCount_, record->GetType());
|
printf("callbackCount_ %zu: type %d\n", callbackCount_, record.GetType());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +371,8 @@ HWTEST_F(VirtualRuntimeTest, UnwindFromRecord, TestSize.Level1)
|
|||||||
(void)memset_s(&attr, sizeof(perf_event_attr), 0, sizeof(perf_event_attr));
|
(void)memset_s(&attr, sizeof(perf_event_attr), 0, sizeof(perf_event_attr));
|
||||||
attr.sample_type = TEST_RECORD_SAMPLE_TYPE;
|
attr.sample_type = TEST_RECORD_SAMPLE_TYPE;
|
||||||
attr.sample_regs_user = TEST_DWARF_RECORD_REGS_USER;
|
attr.sample_regs_user = TEST_DWARF_RECORD_REGS_USER;
|
||||||
PerfRecordSample sample(data.data(), attr);
|
PerfRecordSample sample;
|
||||||
|
sample.Init(data.data(), attr);
|
||||||
sample.DumpLog("UnwindFromRecord");
|
sample.DumpLog("UnwindFromRecord");
|
||||||
ASSERT_EQ(sample.data_.stack_size, TEST_DWARF_RECORD_STACK_SIZE);
|
ASSERT_EQ(sample.data_.stack_size, TEST_DWARF_RECORD_STACK_SIZE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user