Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 6 additions & 27 deletions src/pytest_codspeed/instruments/hooks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ def set_executed_benchmark(self, uri: str, pid: int | None = None) -> None:
if ret != 0:
warnings.warn("Failed to set executed benchmark", RuntimeWarning)

@staticmethod
def current_timestamp() -> int:
def current_timestamp(self) -> int:
"""Return a monotonic timestamp in nanoseconds from the native library."""
from . import dist_instrument_hooks # type: ignore

return dist_instrument_hooks.instrument_hooks_current_timestamp()
return self._module.instrument_hooks_current_timestamp()

def add_marker(
self, marker_type: int, timestamp: int, pid: int | None = None
Expand Down Expand Up @@ -229,31 +226,13 @@ def collect_and_write_python_environment(self) -> None:
self.write_environment()


def callgrind_add_obj_skip(path: str) -> None:
"""Tell callgrind to skip the given object file (and its realpath).

The actual Valgrind client-request trapdoor lives in the C extension; this
just resolves the realpath so callgrind's strcmp matches either form.
"""
if not path or not os.path.exists(path):
return
def callgrind_skip_python_runtime() -> None:
"""Skip libpython and the python executable from callgrind measurement."""
try:
from . import dist_instrument_hooks # type: ignore
except ImportError:
return
Comment on lines 231 to 234
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This funciton should be a class function of InstrumentHooks, and use self._module.callgrind_add_obj_skip

I've pushed a commit to remove a similar import I had added which was absolutely not necessary


dist_instrument_hooks.callgrind_add_obj_skip(path.encode())

# The dynamic loader maps the realpath (e.g. libpython3.12.so.1.0), and
# callgrind stores that in obj_node->name. Skip both so the exact strcmp
# matches regardless of which path callgrind sees.
real = os.path.realpath(path)
if real != path:
dist_instrument_hooks.callgrind_add_obj_skip(real.encode())


def callgrind_skip_python_runtime() -> None:
"""Skip libpython and the python executable from callgrind measurement."""
ldlibrary = sysconfig.get_config_var("LDLIBRARY")
libdir = sysconfig.get_config_var("LIBDIR")
libpython = next(
Expand All @@ -268,6 +247,6 @@ def callgrind_skip_python_runtime() -> None:
None,
)
if libpython:
callgrind_add_obj_skip(libpython)
dist_instrument_hooks.callgrind_add_obj_skip(libpython.encode())

callgrind_add_obj_skip(sys.executable)
dist_instrument_hooks.callgrind_add_obj_skip(sys.executable.encode())
13 changes: 3 additions & 10 deletions src/pytest_codspeed/instruments/hooks/instrument_hooks_module.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "core.h"
#include "valgrind.h"

/* CodSpeed-specific Valgrind client request: tell callgrind to skip an
* object file by path. Not present in upstream callgrind.h. */
// TODO(COD-2654): Move this to instrument-hooks and just call it here
#define VG_USERREQ__ADD_OBJ_SKIP 0x43540006

/* Capsule destructor for InstrumentHooks pointer */
static void instrument_hooks_capsule_destructor(PyObject *capsule) {
Expand Down Expand Up @@ -248,15 +242,14 @@ static PyObject *py_instrument_hooks_write_environment(PyObject *self, PyObject
return PyLong_FromLong(result);
}

/* callgrind_add_obj_skip(path: bytes) -> None
* Outside Valgrind this expands to a nop, so it's safe on bare metal. */
/* callgrind_add_obj_skip(path: bytes) -> int */
static PyObject *py_callgrind_add_obj_skip(PyObject *self, PyObject *args) {
const char *path;
if (!PyArg_ParseTuple(args, "y", &path)) {
return NULL;
}
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_OBJ_SKIP, path, 0, 0, 0, 0);
Py_RETURN_NONE;
uint8_t result = instrument_hooks_callgrind_add_obj_skip(path);
return PyLong_FromLong(result);
}

/* Method definitions */
Expand Down
Loading