From: Gautam Menghani <gautam@linux.ibm.com>
To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
namhyung@kernel.org, mark.rutland@arm.com,
alexander.shishkin@linux.intel.com, jolsa@kernel.org,
irogers@google.com, adrian.hunter@intel.com,
kan.liang@linux.intel.com
Cc: Gautam Menghani <gautam@linux.ibm.com>,
maddy@linux.ibm.com, linux-perf-users@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] perf python: Add support for record_opts struct
Date: Mon, 28 Jul 2025 11:29:27 +0530 [thread overview]
Message-ID: <20250728055937.58531-2-gautam@linux.ibm.com> (raw)
In-Reply-To: <20250728055937.58531-1-gautam@linux.ibm.com>
Add support for record_opts struct to allow python to control the
initialization of the evsels instead of using the current default
options.
Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
---
tools/perf/util/python.c | 186 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 183 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 2f28f71325a8..8537edbb3b0b 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1045,6 +1045,169 @@ static int pyrf_evsel__setup_types(void)
return PyType_Ready(&pyrf_evsel__type);
}
+struct pyrf_target {
+ PyObject_HEAD
+
+ struct target target;
+};
+
+static int pyrf_target__init(struct pyrf_target *target,
+ PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "pid", "tid", "cpu_list", "bpf_str", "system_wide", "uses_mmap",
+ "default_per_cpu", "per_thread", "use_bpf", "inherit",
+ "initial_delay", "attr_map", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssppppppis",
+ kwlist, &(target->target.pid), &(target->target.tid),
+ &(target->target.cpu_list), &(target->target.bpf_str),
+ &(target->target.system_wide),
+ &(target->target.uses_mmap),
+ &(target->target.default_per_cpu),
+ &(target->target.per_thread), &(target->target.use_bpf),
+ &(target->target.inherit), &(target->target.initial_delay),
+ &(target->target.attr_map)))
+ return -1;
+
+ return 0;
+}
+
+static void pyrf_target__delete(struct pyrf_target *target)
+{
+ Py_TYPE(target)->tp_free((PyObject *)target);
+}
+
+static const char pyrf_target__doc[] = PyDoc_STR("target object.");
+
+static PyTypeObject pyrf_target__type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "perf.target",
+ .tp_basicsize = sizeof(struct pyrf_target),
+ .tp_dealloc = (destructor)pyrf_target__delete,
+ .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ .tp_doc = pyrf_target__doc,
+ .tp_init = (initproc)pyrf_target__init,
+};
+
+static int pyrf_target__setup_types(void)
+{
+ pyrf_target__type.tp_new = PyType_GenericNew;
+ return PyType_Ready(&pyrf_target__type);
+}
+
+struct pyrf_record_opts {
+ PyObject_HEAD
+
+ struct record_opts opts;
+};
+
+static int pyrf_record_opts__init(struct pyrf_record_opts *popts,
+ PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "target", "inherit_stat", "no_buffering", "no_inherit",
+ "no_inherit_set", "no_samples", "raw_samples",
+ "sample_address", "sample_phys_addr", "sample_data_page_size",
+ "sample_code_page_size", "sample_weight", "sample_time",
+ "sample_time_set", "sample_cpu", "sample_identifier",
+ "sample_data_src", "period", "period_set", "running_time",
+ "full_auxtrace", "auxtrace_snapshot_mode",
+ "auxtrace_snapshot_on_exit", "auxtrace_sample_mode",
+ "record_namespaces", "record_cgroup", "record_switch_events",
+ "record_switch_events_set", "all_kernel", "all_user",
+ "kernel_callchains", "user_callchains", "tail_synthesize",
+ "overwrite", "ignore_missing_thread", "strict_freq", "sample_id",
+ "no_bpf_event", "kcore", "text_poke", "build_id", "freq",
+ "mmap_pages", "auxtrace_mmap_pages", "user_freq", "branch_stack",
+ "sample_intr_regs", "sample_user_regs", "default_interval",
+ "user_interval", "auxtrace_snapshot_size", "auxtrace_snapshot_opts",
+ "auxtrace_sample_opts", "sample_transaction", "use_clockid",
+ "clockid", "clockid_res_ns", "nr_cblocks", "affinity", "mmap_flush",
+ "comp_level", "nr_threads_synthesize", "ctl_fd", "ctl_fd_ack",
+ "ctl_fd_close", "synth", "threads_spec", "threads_user_spec",
+ "off_cpu_thresh_ns", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "|OppppppppppppppppppppppppppppppppppppppppIIIIIIIIIIssppiIiiiIIiipiisI",
+ kwlist, &(popts->opts.target), &(popts->opts.inherit_stat),
+ &(popts->opts.no_buffering), &(popts->opts.no_inherit),
+ &(popts->opts.no_inherit_set), &(popts->opts.no_samples),
+ &(popts->opts.raw_samples), &(popts->opts.sample_address),
+ &(popts->opts.sample_phys_addr),
+ &(popts->opts.sample_data_page_size),
+ &(popts->opts.sample_code_page_size),
+ &(popts->opts.sample_weight),
+ &(popts->opts.sample_time), &(popts->opts.sample_time_set),
+ &(popts->opts.sample_cpu),
+ &(popts->opts.sample_identifier),
+ &(popts->opts.sample_data_src), &(popts->opts.period),
+ &(popts->opts.period_set), &(popts->opts.running_time),
+ &(popts->opts.full_auxtrace),
+ &(popts->opts.auxtrace_snapshot_mode),
+ &(popts->opts.auxtrace_snapshot_on_exit),
+ &(popts->opts.auxtrace_sample_mode),
+ &(popts->opts.record_namespaces),
+ &(popts->opts.record_cgroup),
+ &(popts->opts.record_switch_events),
+ &(popts->opts.record_switch_events_set),
+ &(popts->opts.all_kernel), &(popts->opts.all_user),
+ &(popts->opts.kernel_callchains),
+ &(popts->opts.user_callchains),
+ &(popts->opts.tail_synthesize),
+ &(popts->opts.overwrite),
+ &(popts->opts.ignore_missing_thread),
+ &(popts->opts.strict_freq), &(popts->opts.sample_id),
+ &(popts->opts.no_bpf_event), &(popts->opts.kcore),
+ &(popts->opts.text_poke), &(popts->opts.build_id),
+ &(popts->opts.freq), &(popts->opts.mmap_pages),
+ &(popts->opts.auxtrace_mmap_pages),
+ &(popts->opts.user_freq),
+ &(popts->opts.branch_stack),
+ &(popts->opts.sample_intr_regs),
+ &(popts->opts.sample_user_regs),
+ &(popts->opts.default_interval),
+ &(popts->opts.user_interval),
+ &(popts->opts.auxtrace_snapshot_size),
+ &(popts->opts.auxtrace_snapshot_opts),
+ &(popts->opts.auxtrace_sample_opts),
+ &(popts->opts.sample_transaction),
+ &(popts->opts.use_clockid),
+ &(popts->opts.clockid), &(popts->opts.clockid_res_ns),
+ &(popts->opts.nr_cblocks), &(popts->opts.affinity),
+ &(popts->opts.mmap_flush), &(popts->opts.comp_level),
+ &(popts->opts.nr_threads_synthesize),
+ &(popts->opts.ctl_fd),
+ &(popts->opts.ctl_fd_ack), &(popts->opts.ctl_fd_close),
+ &(popts->opts.synth), &(popts->opts.threads_spec),
+ &(popts->opts.threads_user_spec),
+ &(popts->opts.off_cpu_thresh_ns)))
+ return -1;
+
+ return 0;
+}
+
+static const char pyrf_record_opts__doc[] = PyDoc_STR("perf record_opts object.");
+
+static void pyrf_record_opts__delete(struct pyrf_record_opts *perf_record_opts)
+{
+ Py_TYPE(perf_record_opts)->tp_free((PyObject *)perf_record_opts);
+}
+
+static PyTypeObject pyrf_record_opts__type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "perf.record_opts",
+ .tp_basicsize = sizeof(struct pyrf_record_opts),
+ .tp_dealloc = (destructor)pyrf_record_opts__delete,
+ .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ .tp_doc = pyrf_record_opts__doc,
+ .tp_init = (initproc)pyrf_record_opts__init,
+};
+
+static int pyrf_record_opts__setup_types(void)
+{
+ pyrf_record_opts__type.tp_new = PyType_GenericNew;
+ return PyType_Ready(&pyrf_record_opts__type);
+}
+
struct pyrf_evlist {
PyObject_HEAD
@@ -1263,7 +1426,7 @@ static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist)
return Py_None;
}
-static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
+static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs)
{
struct record_opts opts = {
.sample_time = true,
@@ -1281,8 +1444,17 @@ static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
.no_buffering = true,
.no_inherit = true,
};
+ PyObject *popts = NULL;
+ static char *kwlist[] = { "record_opts", NULL };
struct evlist *evlist = &pevlist->evlist;
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
+ &popts))
+ return NULL;
+
+ if (popts)
+ opts = ((struct pyrf_record_opts *) popts)->opts;
+
evlist__config(evlist, &opts, &callchain_param);
Py_INCREF(Py_None);
return Py_None;
@@ -1354,7 +1526,7 @@ static PyMethodDef pyrf_evlist__methods[] = {
{
.ml_name = "config",
.ml_meth = (PyCFunction)pyrf_evlist__config,
- .ml_flags = METH_NOARGS,
+ .ml_flags = METH_VARARGS | METH_KEYWORDS,
.ml_doc = PyDoc_STR("Apply default record options to the evlist.")
},
{
@@ -1718,7 +1890,9 @@ PyMODINIT_FUNC PyInit_perf(void)
pyrf_evsel__setup_types() < 0 ||
pyrf_thread_map__setup_types() < 0 ||
pyrf_cpu_map__setup_types() < 0 ||
- pyrf_counts_values__setup_types() < 0)
+ pyrf_counts_values__setup_types() < 0 ||
+ pyrf_target__setup_types() < 0 ||
+ pyrf_record_opts__setup_types() < 0)
return module;
/* The page_size is placed in util object. */
@@ -1766,6 +1940,12 @@ PyMODINIT_FUNC PyInit_perf(void)
Py_INCREF(&pyrf_counts_values__type);
PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type);
+ Py_INCREF(&pyrf_target__type);
+ PyModule_AddObject(module, "target", (PyObject *)&pyrf_target__type);
+
+ Py_INCREF(&pyrf_record_opts__type);
+ PyModule_AddObject(module, "record_opts", (PyObject *)&pyrf_record_opts__type);
+
dict = PyModule_GetDict(module);
if (dict == NULL)
goto error;
--
2.49.0
next prev parent reply other threads:[~2025-07-28 6:00 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-28 5:59 [PATCH 0/2] perf python: Add an example for sampling Gautam Menghani
2025-07-28 5:59 ` Gautam Menghani [this message]
2025-07-28 5:59 ` [PATCH 2/2] perf python: Add sampling.py as " Gautam Menghani
2025-08-12 5:22 ` [PATCH 0/2] perf python: Add an " Gautam Menghani
2025-08-26 7:07 ` Gautam Menghani
2025-09-16 13:30 ` Gautam Menghani
2025-09-16 19:25 ` Arnaldo Carvalho de Melo
2025-09-16 20:07 ` Ian Rogers
2025-09-17 12:37 ` Arnaldo Carvalho de Melo
2025-09-17 15:29 ` Ian Rogers
2025-09-17 16:41 ` Arnaldo Carvalho de Melo
2025-09-17 17:26 ` Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250728055937.58531-2-gautam@linux.ibm.com \
--to=gautam@linux.ibm.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=maddy@linux.ibm.com \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.