libkperf — это легковесная библиотека для сбора производительности на Linux, которая позволяет разработчикам собирать данные о производительности с использованием API. libkperf предоставляет данные о производительности в памяти и позволяет разработчикам обрабатывать данные напрямую, снижая накладные расходы на запись и чтение perf.data.
v1.3:
v1.2:
v1.1:
v1.0:
Минимальная требуемая версия GCC:
Минимальная требуемая версия Python:
Для сборки библиотеки с C API:
git clone --recurse-submodules https://gitee.com/openeuler/libkperf.git
cd libkperf
bash build.sh install_path=/path/to/install
Примечание:
Для сборки библиотеки с отладочной версией:
bash build.sh install_path=/path/to/install build_type=debug
Для сборки пакета Python:
bash build.sh install_path=/path/to/install python=true
Для удаления пакета Python:
python3 -m pip uninstall -y libkperf
Для сборки пакета Go:
bash build.sh go=true
После успешного выполнения команды скопируйте go/src/libkperf в GOPATH/src. GOPATH указывает на директорию проекта пользователя.
См. каталог docs
для подробной документации:
См. каталог docs
для спецификации API Python:
Все функции PMU выполняются следующими интерфейсами:
Вот несколько примеров:
#include <iostream>
#include "symbol.h"
#include "pmu.h"
#include "pcerrc.h"
int main() {
int pid = getpid();
int pidList[1];
pidList[0] = pid;
char *evtList[1];
evtList[0] = "cycles";
// Инициализация списка событий и списка PID в PmuAttr.
// В списке одно событие, называемое 'cycles'.
PmuAttr attr = {0};
attr.evtList = evtList;
attr.numEvt = 1;
attr.pidList = pidList;
attr.numPid = 1;
// Вызов PmuOpen и возвращение дескриптора PMU <pd>.
// <pd> является идентификатором текущей задачи.
int pd = PmuOpen(COUNTING, &attr);
// Начало сбора данных.
PmuEnable(pd);
// Сбор данных в течение одной секунды.
sleep(1);
// Остановка сбора данных.
PmuDisable(pd);
PmuData *data = NULL;
// Чтение данных PMU. Вы также можете читать данные до PmuDisable.
int len = PmuRead(pd, &data);
for (int i = 0; i < len; ++i) {
PmuData *d = &data[i];
std::cout << "evt=" << d->evt << "count=" << d->count << std::endl;
}
// Для освобождения PmuData вызовите PmuDataFree.
PmuDataFree(data);
// Как и для fd, вызовите PmuClose, если pd больше не будет использоваться.
PmuClose(pd);
}
#include <iostream>
#include "symbol.h"
#include "pmu.h"
#include "pcerrc.h"
int main() {
int pid = getpid();
int pidList[1];
pidList[0] = pid;
char *evtList[1];
evtList[0] = "cycles";
// Инициализация списка событий и списка PID в PmuAttr.
// В списке одно событие, называемое 'cycles'.
PmuAttr attr = {0};
attr.evtList = evtList;
attr.numEvt = 1;
attr.pidList = pidList;
attr.numPid = 1;
// Вызов PmuOpen и возвращение дескриптора PMU <pd>.
// <pd> является идентификатором текущей задачи.
// Используйте SAMPLING для выборки задачи.
int pd = PmuOpen(SAMPLING, &attr);
// Начало сбора данных.
PmuEnable(pd);
// Сбор данных в течение одной секунды.
sleep(1);
// Остановка сбора данных.
PmuDisable(pd);
PmuData *data = NULL;
// Чтение данных PMU. Вы также можете читать данные до PmuDisable.
int len = PmuRead(pd, &data);
for (int i = 0; i < len; ++i) {
// Получение элемента из массива.
PmuData *d = &data[i];
// Получение объекта стека, который является связанным списком.
Stack *stack = d->stack;
while (stack) {
// Получение объекта символа.
if (stack->symbol) {
Symbol *data = stack->symbol;
std::cout << std::hex << data->addr << " " << data->symbolName << "+0x" << data->offset << " "
<< data->codeMapAddr << " (" << data->module << ")"
<< " (" << std::dec << data->fileName << ":" << data->lineNum << ")" << std::endl;
}
stack = stack->next;
}
}
// Для освобождения PmuData вызовите PmuDataFree.
PmuDataFree(data);
// Как и для fd, вызовите PmuClose, если pd больше не будет использоваться.
PmuClose(pd);
}
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)
import "libkperf/kperf"
import "fmt"
import "time"
func main() {
attr := kperf.PmuAttr{EvtList:[]string{"cycles"}, SymbolMode:kperf.ELF}
fd, err := kperf.PmuOpen(kperf.COUNT, attr)
if err != nil {
fmt.Printf("kperf pmuopen counting failed, expect err is nil, but is %v\n", err)
return
}
kperf.PmuEnable(fd)
time.Sleep(time.Second)
kperf.PmuDisable(fd)
dataVo, err := kperf.PmuRead(fd)
if err != nil {
fmt.Printf("kperf pmuread failed, expect err is nil, but is %v\n", err)
return
}
for _, o := range dataVo.GoData {
fmt.Printf("event: %v count: %v\n", o.Evt, o.Count)
}
kperf.PmuDataFree(dataVo)
kperf.PmuClose(fd)
}
Команда компиляции:
g++ -o example example.cpp -I /install_path/include -L /install_path/lib -lkperf -lsym
Команда запуска:
python example.py
export GO111MODULE=off
export LD_LIBRARY_PATH=../libkperf/lib:$LD_LIBRARY_PATH
go test -v # запуск всех тестов
go test -v -test.run TestCount # запуск конкретного тестового случая
go build -tags="static"
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )