From 12e9bbe250e62d7ce7912a0671dfdce125e7fc41 Mon Sep 17 00:00:00 2001 From: glx Date: Thu, 17 Jul 2025 18:59:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95=E5=AF=B9?= =?UTF-8?q?=E5=A4=9A=E4=BA=8B=E4=BB=B6=E8=BE=93=E5=87=BAperf.data=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98;pmu=5Fperfdata=E6=94=AF=E6=8C=81ctrl+c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pmu/dump_perf_data.cpp的evt2id用于映射事件和事件id,key是const char*,是通过pmuattr->evtList初始化该map。 但是libkperf内部会修改pmuattr->evtList的指针,导致const char*发生变化,映射失败。 pmu_perfdata增加对信号的处理,支持ctrl+c --- example/pmu_perfdata.cpp | 35 ++++++++++++++++++++++++++++------- pmu/dump_perf_data.cpp | 16 ++++++++-------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/example/pmu_perfdata.cpp b/example/pmu_perfdata.cpp index 906096c..052bb2e 100644 --- a/example/pmu_perfdata.cpp +++ b/example/pmu_perfdata.cpp @@ -36,6 +36,7 @@ PmuFile file = NULL; int lastErr = SUCCESS; bool verbose = false; int64_t startTs = 0; +bool interrupt = false; struct Param { vector events; @@ -84,13 +85,24 @@ static void PrintHelp() std::cerr << " -e , event list. default: cycles\n"; std::cerr << " -b whether to use brbe.\n"; std::cerr << " -o output file path. default: ./libkperf.data\n"; - std::cerr << " -d count of sampling interval: default: UINT32_MAX\n"; - std::cerr << " -I count of interval. unit: ms. default: 1000\n"; + std::cerr << " -d count of reading: default: UINT32_MAX\n"; + std::cerr << " -I interval for reading buffer. unit: ms. default: 1000\n"; std::cerr << " -p pid of process to attach.\n"; std::cerr << " -F sampling frequency. default: 4000\n"; std::cerr << " -v print verbose log.\n"; } +static int ToInt(const char *str) +{ + char *endptr; + long num = strtol(str, &endptr, 10); + if (*endptr != 0) { + throw invalid_argument("invalid arg: " + string(str)); + } + + return static_cast(num); +} + static Param ParseArgs(int argc, char** argv) { Param param; @@ -109,16 +121,16 @@ static Param ParseArgs(int argc, char** argv) param.dataPath = argv[i+1]; ++i; } else if (strcmp(argv[i], "-d") == 0 && i+1 < argc) { - param.duration = atoi(argv[i+1]); + param.duration = ToInt(argv[i+1]); ++i; } else if (strcmp(argv[i], "-p") == 0 && i+1 < argc) { - param.pidList.push_back(atoi(argv[i+1])); + param.pidList.push_back(ToInt(argv[i+1])); ++i; } else if (strcmp(argv[i], "-F") == 0 && i+1 < argc) { - param.freq = atoi(argv[i+1]); + param.freq = ToInt(argv[i+1]); ++i; } else if (strcmp(argv[i], "-I") == 0 && i+1 < argc) { - param.interval = atoi(argv[i+1]); + param.interval = ToInt(argv[i+1]); ++i; } else if (strcmp(argv[i], "-v") == 0) { verbose = true; @@ -231,6 +243,10 @@ int Collect(const Param ¶m) cerr << Perror() << "\n"; break; } + if (interrupt) { + cout << "Ctrl+C\n"; + break; + } while(toRead.load(memory_order_acquire)); toRead.store(true, memory_order_release); @@ -281,10 +297,15 @@ bool ExecuteCommand(Param ¶m) return true; } +void TermBySignal(int sig) { + interrupt = true; +} + int main(int argc, char** argv) { try { startTs = GetTime(); + signal(SIGINT, TermBySignal); auto param = ParseArgs(argc, argv); if (!param.command.empty() && !ExecuteCommand(param)) { return 0; @@ -302,4 +323,4 @@ int main(int argc, char** argv) } return 0; -} \ No newline at end of file +} diff --git a/pmu/dump_perf_data.cpp b/pmu/dump_perf_data.cpp index 213282b..0b8be0e 100644 --- a/pmu/dump_perf_data.cpp +++ b/pmu/dump_perf_data.cpp @@ -145,7 +145,7 @@ public: // but we assign an ID to each event for all cores. Maybe it has no impact. PrepareEvt2Id(pattr); // Write event id and get offset of event id in the file. - map evt2offset; + map evt2offset; err = WriteEvtIds(evt2id, fd, evt2offset); if (err != SUCCESS) { return err; @@ -284,8 +284,8 @@ private: sample->period = d.period; sample->bnr = branchNr; - // To write branch entries after PerfSample. - perf_branch_entry *bentryList = (perf_branch_entry*)(buffer + offset + sizeof(PerfSample)); + // To write branch entries after PerfSample. + perf_branch_entry *bentryList = (perf_branch_entry*)(buffer + offset + sizeof(PerfSample)); for (size_t i = 0;i < branchNr; ++i) { perf_branch_entry *bentry = &bentryList[i]; bentry->from = d.ext->branchRecords[i].fromAddr; @@ -294,7 +294,7 @@ private: bentry->mispred = d.ext->branchRecords[i].misPred; bentry->predicted = d.ext->branchRecords[i].predicted; } - offset += sample->header.size; + offset += sample->header.size; return SUCCESS; } @@ -483,7 +483,7 @@ private: PERF_SAMPLE_PERIOD | PERF_SAMPLE_BRANCH_STACK; } - PerfFileAttr GetFileAttr(const char *evt, const map &evt2offset) + PerfFileAttr GetFileAttr(const char *evt, const map &evt2offset) { // Now we don't have real perf_event_attr of collection task, // then we synthesize a similar one, only for sampling. @@ -518,7 +518,7 @@ private: } } - int WriteEvtIds(const map &evt2id, const int fd, map &evt2offset) + int WriteEvtIds(const map &evt2id, const int fd, map &evt2offset) { for (auto ei : evt2id) { evt2offset[ei.first] = lseek(fd, 0, SEEK_CUR); @@ -529,7 +529,7 @@ private: return SUCCESS; } - int WriteFileAttrs(const int fd, const PmuAttr *pattr, const map &evt2offset) + int WriteFileAttrs(const int fd, const PmuAttr *pattr, const map &evt2offset) { for (int i = 0;i < pattr->numEvt; ++i) { auto fattr = GetFileAttr(pattr->evtList[i], evt2offset); @@ -623,7 +623,7 @@ private: const char *path = nullptr; PerfFileHeader ph = {0}; int fd = 0; - map evt2id; + map evt2id; set modules; const uint16_t PERF_RECORD_MISC_BUILD_ID_SIZE = (1 << 15); -- Gitee