diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 5c188ab519d60c93d0df7cd0604a6037904b3296..422966547c912866430149b0b549ef28b11ba639 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -11,7 +11,7 @@ # Create: 2024-05-16 # Description: libkperf python module project(python_libkperf) -find_package(PythonInterp REQUIRED) -find_package(PythonLibs REQUIRED) +find_package(PythonInterp 3.7 REQUIRED) +find_package(PythonLibs 3.7 REQUIRED) add_subdirectory(modules) \ No newline at end of file diff --git a/python/modules/__init__.py b/python/modules/__init__.py index 725583e6713bb8e7f409b79b65dbc214bd6e7a2c..77b263d4579eccd45f69cde593529f15068328bb 100644 --- a/python/modules/__init__.py +++ b/python/modules/__init__.py @@ -10,5 +10,5 @@ PURPOSE. See the Mulan PSL v2 for more details. Author: Victor Jin Create: 2024-05-10 -Description: python ksym module +Description: python libkperf modules """ \ No newline at end of file diff --git a/python/modules/_libkperf/Config.py b/python/modules/_libkperf/Config.py index a34945c0c60246b71ed02489a221938535c4659c..f885f3e528f11185acd9cdc67f1d84467c38df1d 100644 --- a/python/modules/_libkperf/Config.py +++ b/python/modules/_libkperf/Config.py @@ -14,7 +14,6 @@ Description: ctype python Config module """ import os import ctypes -from ctypes.util import find_library VERSION_MAJOR = 1 VERSION_MINOR = 0 @@ -38,8 +37,8 @@ def libkperf_path(): return os.path.join(lib_path(), libkperf) -sym_so = ctypes.CDLL(libsym_path()) -kperf_so = ctypes.CDLL(find_library(libkperf_path())) +sym_so = ctypes.CDLL(libsym_path(), mode=ctypes.RTLD_GLOBAL) +kperf_so = ctypes.CDLL(libkperf_path()) __all__ = [ diff --git a/python/modules/_libkperf/Pmu.py b/python/modules/_libkperf/Pmu.py index e3f2f1ee28e52457527ef29ad916d5fdd4b2bbc2..cbf4ee2eceab215cf227ea7c349a58a0dbbc2ed2 100644 --- a/python/modules/_libkperf/Pmu.py +++ b/python/modules/_libkperf/Pmu.py @@ -49,34 +49,40 @@ class CtypesPmuAttr(ctypes.Structure): pidList: List[int] = None, cpuList: List[int] = None, sampleRate: int = 0, - useFreq: bool = False, excludeUser: bool = False, excludeKernel: bool = False, - symbolMode: int = 0, dataFilter: int = 0, evFilter: int = 0, minLatency: int = 0, + useFreq: bool = False, + excludeUser: bool = False, + excludeKernel: bool = False, + symbolMode: int = 0, + dataFilter: int = 0, + evFilter: int = 0, + minLatency: int = 0, *args: Any, **kw: Any): super().__init__(*args, **kw) - if evtList is None: - self.evtList = None - self.numEvt = ctypes.c_uint(0) - else: + if evtList: numEvt = len(evtList) self.evtList = (ctypes.c_char_p * numEvt)(*[evt.encode(UTF_8) for evt in evtList]) self.numEvt = ctypes.c_uint(numEvt) - - if pidList is None: - self.pidList = None - self.numPid = ctypes.c_uint(0) else: + self.evtList = None + self.numEvt = ctypes.c_uint(0) + + if pidList: numPid = len(pidList) self.pidList = (ctypes.c_int * numPid)(*pidList) self.numPid = ctypes.c_uint(numPid) - - if cpuList is None: - self.cpuList = None - self.numCpu = ctypes.c_uint(0) else: + self.pidList = None + self.numPid = ctypes.c_uint(0) + + if cpuList: numCpu = len(cpuList) self.cpuList = (ctypes.c_int * numCpu)(*cpuList) self.numCpu = ctypes.c_uint(numCpu) + else: + self.cpuList = None + self.numCpu = ctypes.c_uint(0) + if not useFreq: self.sampleRate.period = ctypes.c_uint(sampleRate) else: @@ -101,13 +107,25 @@ class PmuAttr: pidList: List[int]=None, cpuList: List[int]=None, sampleRate: int=0, - useFreq: bool = False, excludeUser: bool = False, excludeKernel: bool = False, - symbolMode: int=0, dataFilter: int=0, evFilter: int=0, minLatency: int=0): + useFreq: bool = False, + excludeUser: bool = False, + excludeKernel: bool = False, + symbolMode: int=0, + dataFilter: int=0, + evFilter: int=0, + minLatency: int=0): self.__c_pmu_attr = CtypesPmuAttr( - evtList=evtList, pidList=pidList, cpuList=cpuList, + evtList=evtList, + pidList=pidList, + cpuList=cpuList, sampleRate=sampleRate, - useFreq=useFreq, excludeUser=excludeUser, excludeKernel=excludeKernel, - symbolMode=symbolMode, dataFilter=dataFilter, evFilter=evFilter, minLatency=minLatency + useFreq=useFreq, + excludeUser=excludeUser, + excludeKernel=excludeKernel, + symbolMode=symbolMode, + dataFilter=dataFilter, + evFilter=evFilter, + minLatency=minLatency ) @property @@ -124,13 +142,13 @@ class PmuAttr: @evtList.setter def evtList(self, evtList: List[str]) -> None: - if evtList is None or not evtList: - self.c_pmu_attr.evtList = None - self.c_pmu_attr.numEvt = ctypes.c_uint(0) - else: + if evtList: numEvt = len(evtList) self.c_pmu_attr.evtList = (ctypes.c_char_p * numEvt)(*[evt.encode(UTF_8) for evt in evtList]) self.c_pmu_attr.numEvt = ctypes.c_uint(numEvt) + else: + self.c_pmu_attr.evtList = None + self.c_pmu_attr.numEvt = ctypes.c_uint(0) @property def numPid(self) -> int: @@ -142,13 +160,13 @@ class PmuAttr: @pidList.setter def pidList(self, pidList: List[str]) -> None: - if pidList is None or not pidList: - self.c_pmu_attr.pidList = None - self.c_pmu_attr.numPid = ctypes.c_uint(0) - else: + if pidList: numPid = len(pidList) self.c_pmu_attr.pidList = (ctypes.c_char_p * numPid)(*[pid.encode(UTF_8) for pid in pidList]) self.c_pmu_attr.numPid = ctypes.c_uint(numPid) + else: + self.c_pmu_attr.pidList = None + self.c_pmu_attr.numPid = ctypes.c_uint(0) @property def numCpu(self) -> int: @@ -160,13 +178,13 @@ class PmuAttr: @cpuList.setter def cpuList(self, cpuList: List[str]) -> None: - if cpuList is None or not cpuList: - self.c_pmu_attr.cpuList = None - self.c_pmu_attr.numCpu = ctypes.c_uint(0) - else: + if cpuList: numCpu = len(cpuList) self.c_pmu_attr.cpuList = (ctypes.c_char_p * numCpu)(*[cpu.encode(UTF_8) for cpu in cpuList]) self.c_pmu_attr.numCpu = ctypes.c_uint(numCpu) + else: + self.c_pmu_attr.cpuList = None + self.c_pmu_attr.numCpu = ctypes.c_uint(0) @property @@ -400,7 +418,10 @@ class CtypesPmuData(ctypes.Structure): def __init__(self, stack: CtypesStack = None, evt: str = '', - ts: int = 0, pid: int = 0, tid: int = 0, cpu: int = 0, + ts: int = 0, + pid: int = 0, + tid: int = 0, + cpu: int = 0, cpuTopo: CtypesCpuTopology = None, comm: str = '', period: int = 0, @@ -640,7 +661,6 @@ def PmuRead(pd: int) -> Iterator[PmuData]: c_len_data = c_PmuRead(c_pd, ctypes.byref(c_data)) data_iter = (PmuData.from_c_pmu_data(c_data[i]) for i in range(c_len_data)) - PmuDataFree(c_data) return data_iter @@ -664,6 +684,8 @@ def PmuClose(pd: int) -> None: __all__ = [ 'PmuAttr', + 'CpuTopology', + 'PmuDataExt', 'PmuData', 'PmuOpen', 'PmuEventList', diff --git a/python/modules/_libkperf/Symbol.py b/python/modules/_libkperf/Symbol.py index d277ea39fa0b63df146d27c7a6131f848469e64a..4ef64804f59219ef270b181a96cc39f061028065 100644 --- a/python/modules/_libkperf/Symbol.py +++ b/python/modules/_libkperf/Symbol.py @@ -71,9 +71,14 @@ class Symbol: codeMapAddr: int = 0, count: int = 0): self.__c_sym = CtypesSymbol( - addr=addr, module=module, - symbolName=symbolName, fileName=fileName, lineNum=lineNum, offset=offset, - codeMapEndAddr=codeMapEndAddr, codeMapAddr=codeMapAddr, + addr=addr, + module=module, + symbolName=symbolName, + fileName=fileName, + lineNum=lineNum, + offset=offset, + codeMapEndAddr=codeMapEndAddr, + codeMapAddr=codeMapAddr, count=count ) @@ -406,10 +411,10 @@ def SymResolverDestroy() -> None: __all__ = [ - 'CtypesStack', - 'Stack', 'CtypesSymbol', 'Symbol', + 'CtypesStack', + 'Stack', 'SymResolverRecordKernel', 'SymResolverRecordModule', 'SymResolverRecordModuleNoDwarf', diff --git a/python/modules/kperf/pmu.py b/python/modules/kperf/pmu.py index ecfb62122351184b50e724e0d89470de52eb3398..6c0e69d0508fecb70a8fdb397d22837e37f352fa 100644 --- a/python/modules/kperf/pmu.py +++ b/python/modules/kperf/pmu.py @@ -12,9 +12,10 @@ Author: Victor Jin Create: 2024-05-16 Description: kperf pmu module """ -from typing import Iterator +from typing import Iterator, List import _libkperf +import ksym class PmuTaskType: @@ -75,10 +76,87 @@ class SymbolMode: class PmuAttr(_libkperf.PmuAttr): - pass + + def __init__(self, + evtList: List[str] = None, + pidList: List[int] = None, + cpuList: List[int] = None, + sampleRate: int = 0, + useFreq: bool = False, + excludeUser: bool = False, + excludeKernel: bool = False, + symbolMode: int = 0, + dataFilter: int = 0, + evFilter: int = 0, + minLatency: int = 0): + super().__init__( + evtList=evtList, + pidList=pidList, + cpuList=cpuList, + sampleRate=sampleRate, + useFreq=useFreq, + excludeUser=excludeUser, + excludeKernel=excludeKernel, + symbolMode=symbolMode, + dataFilter=dataFilter, + evFilter=evFilter, + minLatency=minLatency + ) + + +class CpuTopology(_libkperf.CpuTopology): + + def __init__(self, + coreId: int = 0, + numaId: int = 0, + socketId: int = 0): + super().__init__( + coreId=coreId, + numaId=numaId, + socketId=socketId + ) + + +class PmuDataExt(_libkperf.PmuDataExt): + + def __init__(self, + pa: int = 0, + va: int = 0, + event: int = 0): + super().__init__( + pa=pa, + va=va, + event=event + ) + class PmuData(_libkperf.PmuData): - pass + + def __init__(self, + stack: ksym.Stack = None, + evt: str = '', + ts: int = 0, + pid: int = 0, + tid: int = 0, + cpu: int = 0, + cpuTopo: CpuTopology = None, + comm: str = '', + period: int = 0, + count: int = 0, + ext: PmuDataExt = None): + super().__init__( + stack=stack.c_stack if stack else None, + evt=evt, + ts=ts, + pid=pid, + tid=tid, + cpu=cpu, + cpuTopo=cpuTopo.c_cpu_topo if cpuTopo else None, + comm=comm, + period=period, + count=count, + ext=ext.c_pmu_data_ext if ext else None, + ) def open(collect_type: PmuTaskType, pmu_attr: PmuAttr) -> int: @@ -116,6 +194,8 @@ __all__ = [ 'SpeEventFilter', 'SymbolMode', 'PmuAttr', + 'CpuTopology', + 'PmuDataExt', 'PmuData', 'open', 'event_list', @@ -124,4 +204,4 @@ __all__ = [ 'read', 'stop', 'close', -] \ No newline at end of file +] diff --git a/python/modules/ksym/symbol.py b/python/modules/ksym/symbol.py index c02f16d022fce03b0c2c98eb2d6260ba7e3a34cc..8d9338a6f5683a7013160e1a2ae4f57b1b221a40 100644 --- a/python/modules/ksym/symbol.py +++ b/python/modules/ksym/symbol.py @@ -17,12 +17,44 @@ from typing import List, Iterator import _libkperf -class Stack(_libkperf.Stack): - pass +class Symbol(_libkperf.Symbol): + def __init__(self, + addr: int = 0, + module: str = '', + symbolName: str = '', + fileName: str = '', + lineNum: int = 0, + offset: int = 0, + codeMapEndAddr: int = 0, + codeMapAddr: int = 0, + count: int = 0): + super().__init__( + addr=addr, + module=module, + symbolName=symbolName, + fileName=fileName, + lineNum=lineNum, + offset=offset, + codeMapEndAddr=codeMapEndAddr, + codeMapAddr=codeMapAddr, + count=count + ) -class Symbol(_libkperf.Symbol): - pass + +class Stack(_libkperf.Stack): + + def __init__(self, + symbol: Symbol = None, + next: 'Stack' = None, + prev: 'Stack' = None, + count: int = 0): + super().__init__( + symbol=symbol.c_sym if symbol else None, + next=next.c_stack if next else None, + prev=prev.c_stack if next else None, + count=count + ) def record_kernel() -> None: @@ -48,6 +80,10 @@ def free_module(pid: int) -> None: _libkperf.FreeModuleData(pid) +def destroy() -> None: + _libkperf.SymResolverDestroy() + + __all__ = [ 'Stack', 'Symbol', @@ -56,4 +92,5 @@ __all__ = [ 'get_stack', 'get_symbol', 'free_module', -] \ No newline at end of file + 'destroy', +]