blob: 3e69a292eb17d6157409b30dc4b9333c8c585cd2 [file] [log] [blame]
/*
* Copyright (c) Facebook, Inc.
* Licensed under the Apache License, Version 2.0 (the "License")
*/
#pragma once
#include <string>
#include <vector>
#include <linux/perf_event.h>
#include <sys/types.h>
#include "BPF.h"
#include "PyPerfType.h"
namespace ebpf {
namespace pyperf {
class PyPerfUtil {
public:
enum class PyPerfResult : int {
SUCCESS = 0,
INIT_FAIL,
PERF_BUF_OPEN_FAIL,
NO_INIT,
EVENT_ATTACH_FAIL,
EVENT_DETACH_FAIL
};
struct Sample {
pid_t pid;
pid_t tid;
std::string comm;
uint8_t threadStateMatch;
uint8_t gilState;
uint8_t pthreadIDMatch;
uint8_t stackStatus;
std::vector<int32_t> pyStackIds;
explicit Sample(const Event* raw, int rawSize)
: pid(raw->pid),
tid(raw->tid),
comm(raw->comm),
threadStateMatch(raw->thread_state_match),
gilState(raw->gil_state),
pthreadIDMatch(raw->pthread_id_match),
stackStatus(raw->stack_status),
pyStackIds(raw->stack, raw->stack + raw->stack_len) {}
};
// init must be invoked exactly once before invoking profile
PyPerfResult init();
PyPerfResult profile(int64_t sampleRate, int64_t durationMs);
private:
uint32_t lostSymbols_ = 0, totalSamples_ = 0, lostSamples_ = 0, truncatedStack_ = 0;
ebpf::BPF bpf_{0, nullptr, false, "", true};
std::vector<Sample> samples_;
bool initCompleted_{false};
void handleSample(const void* data, int dataSize);
void handleLostSamples(int lostCnt);
friend void handleLostSamplesCallback(void*, uint64_t);
friend void handleSampleCallback(void*, void*, int);
std::string getSymbolName(Symbol& sym) const;
bool tryTargetPid(int pid, PidData& data);
};
} // namespace pyperf
} // namespace ebpf