!645 record对象复用优化采集性能

Merge pull request !645 from yuanye/flyweight
This commit is contained in:
openharmony_ci 2024-11-21 09:47:16 +00:00 committed by Gitee
commit 3d84e3f263
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
22 changed files with 482 additions and 631 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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