# libkperf **Repository Path**: dismark/libkperf ## Basic Information - **Project Name**: libkperf - **Description**: Implement a low overhead pmu collection library, providing abstract interfaces for counting, sampling and symbol resolve. - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 38 - **Created**: 2025-03-13 - **Last Updated**: 2025-03-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # libkperf #### Description libkperf is a lightweight performance collection library on linux, that enables developers to perform performance collection in an API fashion. libkperf provides performance data in memory and allows develops to process data directly, reducing overhead of writing and reading perf.data. #### Supported CPU Architectures - Kunpeng #### Supported OS - openEuler - OpenCloudOS - TencentOS - KylinOS - CentOS #### Build Minimum required GCC version: - gcc-4.8.5 and glibc-2.17. Minimum required Python version: - python-3.7. To build a library with C API: ```shell git clone --recurse-submodules https://gitee.com/openeuler/libkperf.git cd libkperf bash build.sh install_path=/path/to/install ``` Note: - If the compilation error message indicates that numa.h file is missing, you need to first install the corresponding numactl-devel package. - If you encounter a CMake error related to 'Found PythonInterp' during compilation and linking, you need to first install the required python3-devel package. To build a library with debug version: ```shell bash build.sh install_path=/path/to/install buildType=debug ``` To build a python package: ```shell bash build.sh install_path=/path/to/install python=true ``` To uninstall python package: ```shell python3 -m pip uninstall -y libkperf ``` #### Documents Refer to ```docs``` directory for detailed docs: - [Detailed usage](./docs/Details_Usage.md) Refer to ```docs``` directory for python API specification docs: - [Python API specification](./docs/Python_API.md) #### Instructions All pmu functions are accomplished by the following interfaces: * PmuOpen Input pid, core id and event and Open pmu device. * PmuEnable Start collection. * PmuRead Read collection data. * PmuDisable Stop collection. * PmuClose Close pmu device. Here are some examples: * Get pmu count for a process. ```C++ int pidList[1]; pidList[0] = pid; char *evtList[1]; evtList[0] = "cycles"; // Initialize event list and pid list in PmuAttr. // There is one event in list, named 'cycles'. PmuAttr attr = {0}; attr.evtList = evtList; attr.numEvt = 1; attr.pidList = pidList; attr.numPid = 1; // Call PmuOpen and pmu descriptor is return. // is an identity for current task. int pd = PmuOpen(COUNTING, &attr); // Start collection. PmuEnable(pd); // Collect for one second. sleep(1); // Stop collection. PmuDisable(pd); PmuData *data = NULL; // Read pmu data. You can also read data before PmuDisable. int len = PmuRead(pd, &data); for (int i = 0; i < len; ++i) { ... } // To free PmuData, call PmuDataFree. PmuDataFree(data); // Like fd, call PmuClose if pd will not be used. PmuClose(pd); ``` * Sample a process ```C++ int pidList[1]; pidList[0] = pid; char *evtList[1]; evtList[0] = "cycles"; // Initialize event list and pid list in PmuAttr. // There is one event in list, named 'cycles'. PmuAttr attr = {0}; attr.evtList = evtList; attr.numEvt = 1; attr.pidList = pidList; attr.numPid = 1; // Call PmuOpen and pmu descriptor is return. // is an identity for current task. // Use SAMPLING for sample task. int pd = PmuOpen(SAMPLING, &attr); // Start collection. PmuEnable(pd); // Collect for one second. sleep(1); // Stop collection. PmuDisable(pd); PmuData *data = NULL; // Read pmu data. You can also read data before PmuDisable. int len = PmuRead(pd, &data); for (int i = 0; i < len; ++i) { // Get an element from array. PmuData *d = &data[i]; // Get stack object which is a linked list. Stack *stack = d->stack; while (stack) { // Get symbol object. if (stack->symbol) { ... } stack = stack->next; } } // To free PmuData, call PmuDataFree. PmuDataFree(data); // Like fd, call PmuClose if pd will not be used. PmuClose(pd); ``` Python examples: ```python import time from collections import defaultdict import kperf def Counting(): evtList = ["r11", "cycles"] pmu_attr = kperf.PmuAttr(evtList=evtList) pd = kperf.open(kperf.PmuTaskType.COUNTING, pmu_attr) if pd == -1: print(kperf.errorno()) print(kperf.error()) kperf.enable(pd) for _ in range(3): time.sleep(1) data_iter = kperf.read(pd) evtMap = defaultdict(int) for data in data_iter.iter: evtMap[data.evt] += data.count for evt, count in evtMap.items(): print(f"event: {evt} count: {count}") kperf.disable(pd) kperf.close(pd) ``` #### Quick Run Reference for Example Code: * **For C++ Example Code:** You can place the sample code into the main function of a C++ source file, and include the header files related to this dynamic library (#include "symbol.h", #include "pmu.h", #include "pcerrc.h"). Then, use g++ to compile and link this dynamic library to generate an executable file that can be run. Compilation Command Reference: ```bash g++ -o example example.cpp -I /install_path/include -L /install_path/lib -lkperf -lsym ``` * **For Python Example Code:** You can place the sample code into the main function of a Python source file, and import the packages related to this dynamic library (import kperf, import ksym). Running the Python file will then utilize the functionalities provided by these packages. Run Command Reference: ```bash python example.py ```