* [PATCH 0/5] trace-cruncher: Kernel histograms
@ 2021-12-07 14:28 Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 1/5] trace-cruncher: Define Python type for trace histograms Yordan Karadzhov (VMware)
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
Adding support for trace histograms. Only the low level wrapper of
the libtracefs APIs is added here.
Yordan Karadzhov (VMware) (5):
trace-cruncher: Define Python type for trace histograms
trace-cruncher: Define constructor for trace histograms
trace-cruncher: Add APIs to setup a histogram
trace-cruncher: Add APIs for histogram control
trace-cruncher: Add kernel histogram example
examples/hist.py | 66 ++++++
src/common.h | 10 +-
src/ftracepy-utils.c | 526 +++++++++++++++++++++++++++++++++++++++----
src/ftracepy-utils.h | 32 +++
src/ftracepy.c | 63 +++++-
5 files changed, 650 insertions(+), 47 deletions(-)
create mode 100755 examples/hist.py
--
2.32.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] trace-cruncher: Define Python type for trace histograms
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
@ 2021-12-07 14:28 ` Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 2/5] trace-cruncher: Define constructor " Yordan Karadzhov (VMware)
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
The new Python type will be used to implement new APIs for working
with histograms.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
src/ftracepy-utils.h | 2 ++
src/ftracepy.c | 13 ++++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index 70e86ff..da31998 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -28,6 +28,8 @@ struct tracefs_dynevent;
C_OBJECT_WRAPPER_DECLARE(tracefs_dynevent, PyDynevent);
+C_OBJECT_WRAPPER_DECLARE(tracefs_hist, PyTraceHist)
+
PyObject *PyTepRecord_time(PyTepRecord* self);
PyObject *PyTepRecord_cpu(PyTepRecord* self);
diff --git a/src/ftracepy.c b/src/ftracepy.c
index fcc69dd..0f06796 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -168,6 +168,14 @@ C_OBJECT_WRAPPER(tracefs_dynevent, PyDynevent,
dynevent_destroy,
tracefs_dynevent_free)
+static PyMethodDef PyTraceHist_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+C_OBJECT_WRAPPER(tracefs_hist, PyTraceHist,
+ NO_DESTROY,
+ tracefs_hist_free)
+
static PyMethodDef ftracepy_methods[] = {
{"dir",
(PyCFunction) PyFtrace_dir,
@@ -387,6 +395,9 @@ PyMODINIT_FUNC PyInit_ftracepy(void)
if (!PyDyneventTypeInit())
return NULL;
+ if (!PyTraceHistTypeInit())
+ return NULL;
+
TFS_ERROR = PyErr_NewException("tracecruncher.ftracepy.tfs_error",
NULL, NULL);
@@ -403,7 +414,7 @@ PyMODINIT_FUNC PyInit_ftracepy(void)
PyModule_AddObject(module, "tep_record", (PyObject *) &PyTepRecordType);
PyModule_AddObject(module, "tracefs_instance", (PyObject *) &PyTfsInstanceType);
PyModule_AddObject(module, "tracefs_dynevent", (PyObject *) &PyDyneventType);
-
+ PyModule_AddObject(module, "tracefs_hist", (PyObject *) &PyTraceHistType);
PyModule_AddObject(module, "tfs_error", TFS_ERROR);
PyModule_AddObject(module, "tep_error", TEP_ERROR);
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/5] trace-cruncher: Define constructor for trace histograms
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 1/5] trace-cruncher: Define Python type for trace histograms Yordan Karadzhov (VMware)
@ 2021-12-07 14:28 ` Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 3/5] trace-cruncher: Add APIs to setup a histogram Yordan Karadzhov (VMware)
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
A method for creating histogram objects is added. The optional arguments
of the method allows for variety of ways to create histograms.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
src/common.h | 10 ++-
src/ftracepy-utils.c | 195 +++++++++++++++++++++++++++++++++++++++++++
src/ftracepy-utils.h | 3 +
src/ftracepy.c | 5 ++
4 files changed, 210 insertions(+), 3 deletions(-)
diff --git a/src/common.h b/src/common.h
index 9eee563..eacea7d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -26,10 +26,9 @@ static const char *NO_ARG = "/NONE/";
#define TC_NIL_MSG "(nil)"
-static inline bool is_all(const char *arg)
+static inline bool lax_cmp(const char *arg, const char *model)
{
- const char all[] = "all";
- const char *p = &all[0];
+ const char *p = &model[0];
for (; *arg; arg++, p++) {
if (tolower(*arg) != *p)
@@ -38,6 +37,11 @@ static inline bool is_all(const char *arg)
return !(*p);
}
+static inline bool is_all(const char *arg)
+{
+ return lax_cmp(arg, "all");
+}
+
static inline bool is_no_arg(const char *arg)
{
return arg[0] == '\0' || arg == NO_ARG;
diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index 7f3daca..65aca81 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -1954,6 +1954,201 @@ PyObject *PyDynevent_is_enabled(PyDynevent *self, PyObject *args,
return ret;
}
+static enum tracefs_hist_key_type hist_key_type(PyObject * py_type)
+{
+ int type = -1;
+
+ if (PyUnicode_Check(py_type)) {
+ const char *type_str = PyUnicode_DATA(py_type);
+
+ if (lax_cmp(type_str, "normal") ||
+ lax_cmp(type_str, "n") )
+ type = TRACEFS_HIST_KEY_NORMAL;
+ else if (lax_cmp(type_str, "hex") ||
+ lax_cmp(type_str, "h") )
+ type = TRACEFS_HIST_KEY_HEX;
+ else if (lax_cmp(type_str, "sym"))
+ type = TRACEFS_HIST_KEY_SYM;
+ else if (lax_cmp(type_str, "sym_offset") ||
+ lax_cmp(type_str, "so"))
+ type = TRACEFS_HIST_KEY_SYM_OFFSET;
+ else if (lax_cmp(type_str, "syscall") ||
+ lax_cmp(type_str, "sc"))
+ type = TRACEFS_HIST_KEY_SYSCALL;
+ else if (lax_cmp(type_str, "execname") ||
+ lax_cmp(type_str, "e"))
+ type = TRACEFS_HIST_KEY_EXECNAME;
+ else if (lax_cmp(type_str, "log") ||
+ lax_cmp(type_str, "l"))
+ type = TRACEFS_HIST_KEY_LOG;
+ else if (lax_cmp(type_str, "users") ||
+ lax_cmp(type_str, "u"))
+ type = TRACEFS_HIST_KEY_USECS;
+ else if (lax_cmp(type_str, "max") ||
+ lax_cmp(type_str, "m"))
+ type = TRACEFS_HIST_KEY_MAX;
+ else {
+ TfsError_fmt(NULL, "Unknown axis type %s\n",
+ type_str);
+ }
+ } else if (PyLong_CheckExact(py_type)) {
+ type = PyLong_AsLong(py_type);
+ } else {
+ TfsError_fmt(NULL, "Unknown axis type %s\n");
+ }
+
+ return type;
+}
+
+static struct tracefs_hist *hist_from_key(struct tep_handle *tep,
+ const char *system, const char *event,
+ PyObject *py_key, PyObject * py_type)
+{
+ struct tracefs_hist *hist = NULL;
+ int type = 0;
+
+ if (PyUnicode_Check(py_key)) {
+ if (py_type) {
+ type = hist_key_type(py_type);
+ if (type < 0)
+ return NULL;
+ }
+
+ hist = tracefs_hist_alloc(tep, system, event,
+ PyUnicode_DATA(py_key), type);
+ } else if (PyList_CheckExact(py_key)) {
+ int i, n_keys = PyList_Size(py_key);
+ struct tracefs_hist_axis *axes;
+ PyObject *item_type;
+
+ if (py_type) {
+ /*
+ * The format of the types have to match the format
+ * of the keys.
+ */
+ if (!PyList_CheckExact(py_key) ||
+ PyList_Size(py_type) != n_keys)
+ return NULL;
+ }
+
+ axes = calloc(n_keys + 1, sizeof(*axes));
+ if (!axes) {
+ MEM_ERROR
+ return NULL;
+ }
+
+ for (i = 0; i < n_keys; ++i) {
+ axes[i].key = str_from_list(py_key, i);
+ if (!axes[i].key)
+ return NULL;
+
+ if (py_type) {
+ item_type = PyList_GetItem(py_type, i);
+ if (!PyLong_CheckExact(item_type))
+ return NULL;
+
+ type = hist_key_type(item_type);
+ if (type < 0)
+ return NULL;
+
+ axes[i].type = type;
+ }
+ }
+
+ hist = tracefs_hist_alloc_nd(tep, system, event, axes);
+ free(axes);
+ }
+
+ return hist;
+}
+
+static struct tracefs_hist *hist_from_axis(struct tep_handle *tep,
+ const char *system, const char *event,
+ PyObject *py_axes)
+{
+ struct tracefs_hist *hist = NULL;
+ struct tracefs_hist_axis *axes;
+ PyObject *key, *value;
+ Py_ssize_t i = 0;
+ int n_axes;
+
+ n_axes = PyDict_Size(py_axes);
+ if (PyErr_Occurred())
+ return NULL;
+
+ axes = calloc(n_axes + 1, sizeof(*axes));
+ if (!axes) {
+ MEM_ERROR
+ return NULL;
+ }
+
+ while (PyDict_Next(py_axes, &i, &key, &value)) {
+ axes[i - 1].key = PyUnicode_DATA(key);
+ axes[i - 1].type = hist_key_type(value);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ free(axes);
+ return NULL;
+ }
+ }
+
+ hist = tracefs_hist_alloc_nd(tep, system, event, axes);
+ free(axes);
+
+ return hist;
+}
+
+PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] =
+ {"system", "event", "key", "type", "axes", "name", NULL};
+ PyObject *py_axes = NULL, *py_key = NULL, *py_type = NULL;
+ const char *system, *event, *name = NULL;
+ struct tracefs_hist *hist = NULL;
+ struct tep_handle *tep;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "ss|OOOs",
+ kwlist,
+ &system,
+ &event,
+ &py_key,
+ &py_type,
+ &py_axes,
+ &name)) {
+ return NULL;
+ }
+
+ tep = tracefs_local_events(tracefs_tracing_dir());
+ if (!tep)
+ goto fail;
+
+ if (py_key && ! py_axes) {
+ hist = hist_from_key(tep, system, event, py_key, py_type);
+ } else if (!py_key && py_axes) {
+ hist = hist_from_axis(tep, system, event, py_axes);
+ } else {
+ TfsError_setstr(NULL, "'key' or 'axis' must be provided.");
+ return NULL;
+ }
+
+ if (!hist)
+ goto fail;
+
+ if (name && tracefs_hist_add_name(hist, name) < 0)
+ goto fail;
+
+ return PyTraceHist_New(hist);
+
+ fail:
+ TfsError_fmt(NULL, "Failed to create histogram for %s/%s",
+ system, event);
+ tracefs_hist_free(hist);
+ return NULL;
+}
+
PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args,
PyObject *kwargs)
{
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index da31998..f69a6d4 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -178,6 +178,9 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
PyObject *kwargs);
+PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
+ PyObject *kwargs);
+
PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args,
PyObject *kwargs);
diff --git a/src/ftracepy.c b/src/ftracepy.c
index 0f06796..7891b5e 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -327,6 +327,11 @@ static PyMethodDef ftracepy_methods[] = {
METH_VARARGS | METH_KEYWORDS,
"Define a kretprobe."
},
+ {"hist",
+ (PyCFunction) PyFtrace_hist,
+ METH_VARARGS | METH_KEYWORDS,
+ "Define a histogram."
+ },
{"set_ftrace_loglevel",
(PyCFunction) PyFtrace_set_ftrace_loglevel,
METH_VARARGS | METH_KEYWORDS,
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/5] trace-cruncher: Add APIs to setup a histogram
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 1/5] trace-cruncher: Define Python type for trace histograms Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 2/5] trace-cruncher: Define constructor " Yordan Karadzhov (VMware)
@ 2021-12-07 14:28 ` Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 4/5] trace-cruncher: Add APIs for histogram control Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 5/5] trace-cruncher: Add kernel histogram example Yordan Karadzhov (VMware)
4 siblings, 0 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
More methods for controlling the data acquisition of the histogram
are added.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
src/ftracepy-utils.c | 129 +++++++++++++++++++++++++++++++++++++++++++
src/ftracepy-utils.h | 9 +++
src/ftracepy.c | 15 +++++
3 files changed, 153 insertions(+)
diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index 65aca81..d7e6d6a 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -707,6 +707,135 @@ PyObject *PyTfsInstance_dir(PyTfsInstance *self)
return PyUnicode_FromString(tracefs_instance_get_dir(self->ptrObj));
}
+PyObject *PyTraceHist_add_value(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = {"value", NULL};
+ const char *value;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "s",
+ kwlist,
+ &value)) {
+ return NULL;
+ }
+
+ if (tracefs_hist_add_value(self->ptrObj, value) < 0) {
+ MEM_ERROR
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+const char *hist_noname = "unnamed";
+static inline const char *get_hist_name(struct tracefs_hist *hist)
+{
+ const char *name = tracefs_hist_get_name(hist);
+ return name ? name : hist_noname;
+}
+
+static bool add_sort_key(struct tracefs_hist *hist,
+ const char *sort_key)
+{
+ if (tracefs_hist_add_sort_key(hist, sort_key) < 0) {
+ TfsError_fmt(NULL,
+ "Failed to add sort key \'%s\'to histogram \'%s\'.",
+ sort_key, get_hist_name(hist));
+ return false;
+ }
+
+ return true;
+}
+
+PyObject *PyTraceHist_sort_keys(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = {"keys", NULL};
+ PyObject *py_obj;
+ const char *key;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "O",
+ kwlist,
+ &py_obj)) {
+ return NULL;
+ }
+
+ if (PyUnicode_Check(py_obj)) {
+ if (!add_sort_key(self->ptrObj, PyUnicode_DATA(py_obj)))
+ return NULL;
+ } else if (PyList_CheckExact(py_obj)) {
+ int i, n = PyList_Size(py_obj);
+
+ for (i = 0; i < n; ++i) {
+ key = str_from_list(py_obj, i);
+ if (!key ||
+ !add_sort_key(self->ptrObj, key)) {
+ PyErr_SetString(TRACECRUNCHER_ERROR,
+ "Inconsistent \"keys\" argument.");
+ return NULL;
+ }
+ }
+ }
+
+ Py_RETURN_NONE;
+}
+
+static int sort_direction(PyObject *py_dir)
+{
+ int dir = -1;
+
+ if (PyLong_CheckExact(py_dir)) {
+ dir = PyLong_AsLong(py_dir);
+ } else if (PyUnicode_Check(py_dir)) {
+ const char *dir_str = PyUnicode_DATA(py_dir);
+
+ if (lax_cmp(dir_str, "descending") ||
+ lax_cmp(dir_str, "desc") ||
+ lax_cmp(dir_str, "d"))
+ dir = 1;
+ else if (lax_cmp(dir_str, "ascending") ||
+ lax_cmp(dir_str, "asc") ||
+ lax_cmp(dir_str, "a"))
+ dir = 0;
+ }
+
+ return dir;
+}
+
+PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = {"sort_key", "direction", NULL};
+ const char *sort_key;
+ PyObject *py_dir;
+ int dir;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "sO",
+ kwlist,
+ &sort_key,
+ &py_dir)) {
+ return NULL;
+ }
+
+ dir = sort_direction(py_dir);
+
+ if (dir < 0 ||
+ tracefs_hist_sort_key_direction(self->ptrObj, sort_key, dir) < 0) {
+ TfsError_fmt(NULL,
+ "Failed to add sort direction to histogram \'%s\'.",
+ get_hist_name(self->ptrObj));
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
PyObject *PyFtrace_dir(PyObject *self)
{
return PyUnicode_FromString(tracefs_tracing_dir());
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index f69a6d4..07d2cac 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -92,6 +92,15 @@ PyObject *PyDynevent_disable(PyDynevent *self, PyObject *args,
PyObject *PyDynevent_is_enabled(PyDynevent *self, PyObject *args,
PyObject *kwargs);
+PyObject *PyTraceHist_add_value(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_sort_keys(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
PyObject *PyFtrace_dir(PyObject *self);
PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs);
diff --git a/src/ftracepy.c b/src/ftracepy.c
index 7891b5e..b91cda9 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -169,6 +169,21 @@ C_OBJECT_WRAPPER(tracefs_dynevent, PyDynevent,
tracefs_dynevent_free)
static PyMethodDef PyTraceHist_methods[] = {
+ {"add_value",
+ (PyCFunction) PyTraceHist_add_value,
+ METH_VARARGS | METH_KEYWORDS,
+ "Add value field."
+ },
+ {"sort_keys",
+ (PyCFunction) PyTraceHist_sort_keys,
+ METH_VARARGS | METH_KEYWORDS,
+ "Set key felds or values to sort on."
+ },
+ {"sort_key_direction",
+ (PyCFunction) PyTraceHist_sort_key_direction,
+ METH_VARARGS | METH_KEYWORDS,
+ "Set the direction of a sort key field."
+ },
{NULL, NULL, 0, NULL}
};
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/5] trace-cruncher: Add APIs for histogram control
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
` (2 preceding siblings ...)
2021-12-07 14:28 ` [PATCH 3/5] trace-cruncher: Add APIs to setup a histogram Yordan Karadzhov (VMware)
@ 2021-12-07 14:28 ` Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 5/5] trace-cruncher: Add kernel histogram example Yordan Karadzhov (VMware)
4 siblings, 0 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
This is an almost direct wrapping of the corresponding APIs defined in
libtracefs. The 'continue' API (tracefs_hist_continue()) gets renamed
to resume(), because 'continue' is a keyword in Python.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
src/ftracepy-utils.c | 202 ++++++++++++++++++++++++++++++++++---------
src/ftracepy-utils.h | 18 ++++
src/ftracepy.c | 30 +++++++
3 files changed, 207 insertions(+), 43 deletions(-)
diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index d7e6d6a..a735d88 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -836,6 +836,165 @@ PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
Py_RETURN_NONE;
}
+static bool get_optional_instance(PyObject *py_obj,
+ struct tracefs_instance **instance)
+{
+ PyTfsInstance *py_inst;
+
+ if (!py_obj) {
+ *instance = NULL;
+ return true;
+ }
+
+ if (!PyTfsInstance_Check(py_obj)) {
+ PyErr_SetString(TRACECRUNCHER_ERROR,
+ "Passing argument \'instance\' with incompatible type.");
+ return false;
+ }
+
+ py_inst = (PyTfsInstance *)py_obj;
+ *instance = py_inst->ptrObj;
+
+ return true;
+}
+
+bool get_instance_from_arg(PyObject *args, PyObject *kwargs,
+ struct tracefs_instance **instance)
+{
+ static char *kwlist[] = {"instance", NULL};
+ PyObject *py_inst = NULL;
+ *instance = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "|O",
+ kwlist,
+ &py_inst)) {
+ return false;
+ }
+
+ if (!get_optional_instance(py_inst, instance))
+ return NULL;
+
+ return true;
+}
+
+static bool hist_cmd(PyTraceHist *self, PyObject *args, PyObject *kwargs,
+ enum tracefs_hist_command cmd,
+ const char *err_msg)
+{
+ struct tracefs_instance *instance;
+
+ if (!get_instance_from_arg(args, kwargs, &instance))
+ return NULL;
+
+ if (tracefs_hist_command(instance, self->ptrObj, cmd) < 0) {
+ char *buff;
+
+ if (asprintf(&buff, "%s %s",
+ err_msg, get_hist_name(self->ptrObj)) <= 0) {
+ MEM_ERROR;
+ return false;
+ }
+
+ TfsError_setstr(instance, buff);
+ free(buff);
+
+ return false;
+ }
+
+ return true;
+}
+
+PyObject *PyTraceHist_start(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ if (!hist_cmd(self, args, kwargs,
+ TRACEFS_HIST_CMD_START,
+ "Failed to start filling the histogram"))
+ return false;
+
+ Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_stop(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ if (!hist_cmd(self, args, kwargs,
+ TRACEFS_HIST_CMD_PAUSE,
+ "Failed to stop filling the histogram"))
+ return false;
+
+ Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_resume(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ if (!hist_cmd(self, args, kwargs,
+ TRACEFS_HIST_CMD_CONT,
+ "Failed to resume filling the histogram"))
+ return false;
+
+ Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_clear(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ if (!hist_cmd(self, args, kwargs,
+ TRACEFS_HIST_CMD_CLEAR,
+ "Failed to clear the histogram"))
+ return false;
+
+ Py_RETURN_NONE;
+}
+
+static char *hist_read(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct tracefs_instance *instance;
+ const char *hist_file = "hist";
+ char *data;
+
+ if (!get_instance_from_arg(args, kwargs, &instance))
+ return NULL;
+
+ data = tracefs_event_file_read(instance,
+ tracefs_hist_get_system(self->ptrObj),
+ tracefs_hist_get_event(self->ptrObj),
+ hist_file,
+ NULL);
+ if (!data) {
+ TfsError_fmt(instance,
+ "Failed read data from histogram \'%s\'.",
+ get_hist_name(self->ptrObj));
+ }
+
+ return data;
+}
+
+PyObject *PyTraceHist_read(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ char *data = hist_read(self, args, kwargs);
+ PyObject *ret = PyUnicode_FromString(data);
+
+ free(data);
+ return ret;
+}
+
+PyObject *PyTraceHist_close(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs)
+{
+ if (!hist_cmd(self, args, kwargs,
+ TRACEFS_HIST_CMD_DESTROY,
+ "Failed to close the histogram"))
+ return false;
+
+ Py_RETURN_NONE;
+}
+
PyObject *PyFtrace_dir(PyObject *self)
{
return PyUnicode_FromString(tracefs_tracing_dir());
@@ -967,49 +1126,6 @@ PyObject *PyFtrace_find_instance(PyObject *self, PyObject *args,
return py_inst;
}
-static bool get_optional_instance(PyObject *py_obj,
- struct tracefs_instance **instance)
-{
- PyTfsInstance *py_inst;
-
- if (!py_obj) {
- *instance = NULL;
- return true;
- }
-
- if (!PyTfsInstance_Check(py_obj)) {
- PyErr_SetString(TRACECRUNCHER_ERROR,
- "Passing argument \'instance\' with incompatible type.");
- return false;
- }
-
- py_inst = (PyTfsInstance *)py_obj;
- *instance = py_inst->ptrObj;
-
- return true;
-}
-
-bool get_instance_from_arg(PyObject *args, PyObject *kwargs,
- struct tracefs_instance **instance)
-{
- static char *kwlist[] = {"instance", NULL};
- PyObject *py_inst = NULL;
- *instance = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args,
- kwargs,
- "|O",
- kwlist,
- &py_inst)) {
- return false;
- }
-
- if (!get_optional_instance(py_inst, instance))
- return NULL;
-
- return true;
-}
-
PyObject *PyFtrace_available_tracers(PyObject *self, PyObject *args,
PyObject *kwargs)
{
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index 07d2cac..d09c8bf 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -101,6 +101,24 @@ PyObject *PyTraceHist_sort_keys(PyTraceHist *self, PyObject *args,
PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
PyObject *kwargs);
+PyObject *PyTraceHist_start(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_stop(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_resume(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_clear(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_read(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyTraceHist_close(PyTraceHist *self, PyObject *args,
+ PyObject *kwargs);
+
PyObject *PyFtrace_dir(PyObject *self);
PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs);
diff --git a/src/ftracepy.c b/src/ftracepy.c
index b91cda9..b270b71 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -184,6 +184,36 @@ static PyMethodDef PyTraceHist_methods[] = {
METH_VARARGS | METH_KEYWORDS,
"Set the direction of a sort key field."
},
+ {"start",
+ (PyCFunction) PyTraceHist_start,
+ METH_VARARGS | METH_KEYWORDS,
+ "Start acquiring data."
+ },
+ {"stop",
+ (PyCFunction) PyTraceHist_stop,
+ METH_VARARGS | METH_KEYWORDS,
+ "Pause acquiring data."
+ },
+ {"resume",
+ (PyCFunction) PyTraceHist_resume,
+ METH_VARARGS | METH_KEYWORDS,
+ "Continue acquiring data."
+ },
+ {"clear",
+ (PyCFunction) PyTraceHist_clear,
+ METH_VARARGS | METH_KEYWORDS,
+ "Reset the histogram."
+ },
+ {"read",
+ (PyCFunction) PyTraceHist_read,
+ METH_VARARGS | METH_KEYWORDS,
+ "Read the content of the histogram."
+ },
+ {"close",
+ (PyCFunction) PyTraceHist_close,
+ METH_VARARGS | METH_KEYWORDS,
+ "Destroy the histogram."
+ },
{NULL, NULL, 0, NULL}
};
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/5] trace-cruncher: Add kernel histogram example
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
` (3 preceding siblings ...)
2021-12-07 14:28 ` [PATCH 4/5] trace-cruncher: Add APIs for histogram control Yordan Karadzhov (VMware)
@ 2021-12-07 14:28 ` Yordan Karadzhov (VMware)
4 siblings, 0 replies; 6+ messages in thread
From: Yordan Karadzhov (VMware) @ 2021-12-07 14:28 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
This is a very basic possible example, demonstration the usage of
the new APIs for kernel histograms.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
examples/hist.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100755 examples/hist.py
diff --git a/examples/hist.py b/examples/hist.py
new file mode 100755
index 0000000..d668039
--- /dev/null
+++ b/examples/hist.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+"""
+SPDX-License-Identifier: CC-BY-4.0
+
+Copyright 2021 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+"""
+
+import sys
+import time
+
+import tracecruncher.ftracepy as ft
+
+inst_name = 'khist_example'
+
+cmds = ['start', 'stop', 'show', 'continue', 'clear', 'close']
+
+def get_hist():
+ hist = ft.hist(name='h1',
+ system='kmem',
+ event='kmalloc',
+ axes={'call_site': 'sym',
+ 'bytes_req': 'n'})
+
+ hist.add_value(value='bytes_alloc')
+ hist.sort_keys(keys=['bytes_req', 'bytes_alloc'])
+ hist.sort_key_direction(sort_key='bytes_req', direction='desc')
+
+ return hist
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ sys.exit(1)
+
+ if not sys.argv[1].isdigit() and not sys.argv[1] in cmds:
+ sys.exit(1)
+
+ arg1 = sys.argv[1]
+ if arg1.isdigit() or arg1 == 'start':
+ inst = ft.create_instance(name=inst_name)
+ hist = get_hist()
+ hist.start(inst)
+
+ if arg1.isdigit():
+ time.sleep(int(arg1))
+ hist.stop(inst)
+ print(hist.read(inst))
+ hist.close(inst)
+ else:
+ ft.detach(inst)
+ else:
+ inst = ft.find_instance(name=inst_name)
+ hist = get_hist()
+
+ if arg1 == 'stop':
+ hist.stop(inst)
+ elif arg1 == 'show':
+ print(hist.read(inst))
+ elif arg1 == 'continue':
+ hist.resume(inst)
+ elif arg1 == 'clear':
+ hist.clear(inst)
+
+ if arg1 == 'close':
+ ft.attach(inst)
+ hist.close(inst)
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-12-07 14:29 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-07 14:28 [PATCH 0/5] trace-cruncher: Kernel histograms Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 1/5] trace-cruncher: Define Python type for trace histograms Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 2/5] trace-cruncher: Define constructor " Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 3/5] trace-cruncher: Add APIs to setup a histogram Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 4/5] trace-cruncher: Add APIs for histogram control Yordan Karadzhov (VMware)
2021-12-07 14:28 ` [PATCH 5/5] trace-cruncher: Add kernel histogram example Yordan Karadzhov (VMware)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).