linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Build trace-cruncher as Python pakage
@ 2019-12-12  9:02 Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 1/5] Refactor the part of the interface that relies on libkshark Yordan Karadzhov (VMware)
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

This patch-set is an attempt to restructure the project and to make it
build as a native Python package. Although it looks like a complete
rewrite, this is essentially just a switching from using Cython to using
directly the C API of Python. Cython is still being used but only for
the implementation of the NumPy data wrapper. The new package has its
own stand-alone build system (very primitive for the moment) that is
completely decoupled from the existing build system used by tracecruncher.
In order to build and install the new package do:

sudo python setup.py install --record files.txt

The patch-set does not  remove the old implementation yet. This will
happen in another successive patch-set.

Please review as careful as possible!

Yordan Karadzhov (VMware) (5):
  Refactor the part of the interface that relies on libkshark
  Refactor the part of the interface that relies on libtraceevent
  Refactor NumPy based data wrapper
  Add "utils"
  Adapt the sched_wakeup.py example script to use the new tracecruncher
    module

 examples/sched_wakeup.py  |  30 ++---
 setup.py                  |  61 +++++++++
 src/common.h              |  20 +++
 src/datawrapper.pyx       | 201 ++++++++++++++++++++++++++++
 src/ftracepy.c            | 234 +++++++++++++++++++++++++++++++++
 src/ksharkpy.c            | 268 ++++++++++++++++++++++++++++++++++++++
 src/trace2matrix.c        |  29 +++++
 tracecruncher/__init__.py |   0
 tracecruncher/utils.py    |  54 ++++++++
 9 files changed, 882 insertions(+), 15 deletions(-)
 create mode 100644 setup.py
 create mode 100644 src/common.h
 create mode 100644 src/datawrapper.pyx
 create mode 100644 src/ftracepy.c
 create mode 100644 src/ksharkpy.c
 create mode 100644 src/trace2matrix.c
 create mode 100644 tracecruncher/__init__.py
 create mode 100644 tracecruncher/utils.py

-- 
2.20.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] Refactor the part of the interface that relies on libkshark
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
@ 2019-12-12  9:02 ` Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 2/5] Refactor the part of the interface that relies on libtraceevent Yordan Karadzhov (VMware)
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

This is the first patch from a patch-set that aims to refactor
trace-cruncher completely. The goal it to be able to build the
project as a native Python package, which contains several
sub-packages implemented as C extensions via the Python's C API.
In this patch the part of the interface that relies on libkshark
gets re-implemented as an extension called "tracecruncher.ksharkpy".
Note that this new extension has a stand-alone build that is
completely decoupled from the existing build system used by
trace-cruncher.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 setup.py                  |  44 +++++++
 src/common.h              |  19 +++
 src/ksharkpy.c            | 268 ++++++++++++++++++++++++++++++++++++++
 tracecruncher/__init__.py |   0
 4 files changed, 331 insertions(+)
 create mode 100644 setup.py
 create mode 100644 src/common.h
 create mode 100644 src/ksharkpy.c
 create mode 100644 tracecruncher/__init__.py

diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..6a1d2e8
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+"""
+SPDX-License-Identifier: LGPL-2.1
+
+Copyright 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+"""
+
+
+from setuptools import setup, find_packages
+from distutils.core import Extension
+from Cython.Build import cythonize
+
+def main():
+    kshark_path = '/usr/local/lib/kernelshark'
+
+    module_ks = Extension('tracecruncher.ksharkpy',
+                          sources=['src/ksharkpy.c'],
+                          library_dirs=[kshark_path],
+                          runtime_library_dirs=[kshark_path],
+                          libraries=['kshark'],
+                          define_macros=[
+                              ('LIB_KSHARK_PATH', '\"' + kshark_path + '/libkshark.so\"'),
+                              ('KS_PLUGIN_DIR',   '\"' + kshark_path + '/plugins\"')
+                              ],
+                          )
+
+    setup(name='tracecruncher',
+          version='0.1.0',
+          description='NumPy based interface for accessing tracing data in Python.',
+          author='Yordan Karadzhov (VMware)',
+          author_email='y.karadz@gmail.com',
+          url='https://github.com/vmware/trace-cruncher',
+          license='LGPL-2.1',
+          packages=find_packages(),
+          ext_modules=[module_ks],
+          classifiers=[
+              'Development Status :: 3 - Alpha',
+              'Programming Language :: Python :: 3',
+              ]
+          )
+
+if __name__ == '__main__':
+    main()
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..d7d355a
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+
+/*
+ * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+#ifndef _TC_COMMON_H
+#define _TC_COMMON_H
+
+#define TRACECRUNCHER_ERROR	tracecruncher_error
+#define KSHARK_ERROR		kshark_error
+
+#define KS_INIT_ERROR \
+	PyErr_SetString(KSHARK_ERROR, "libshark failed to initialize");
+
+#define KS_MEM_ERROR \
+	PyErr_SetString(TRACECRUNCHER_ERROR, "failed to allocate memory");
+
+#endif
diff --git a/src/ksharkpy.c b/src/ksharkpy.c
new file mode 100644
index 0000000..90a6c1f
--- /dev/null
+++ b/src/ksharkpy.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+ */
+
+/** Use GNU C Library. */
+#define _GNU_SOURCE 1
+
+// C
+#include <stdio.h>
+#include <dlfcn.h>
+
+// Python
+#include <Python.h>
+
+// KernelShark
+#include "kernelshark/libkshark.h"
+#include "kernelshark/libkshark-input.h"
+#include "kernelshark/libkshark-plugin.h"
+#include "kernelshark/libkshark-model.h"
+
+// trace-cruncher
+#include "common.h"
+
+static PyObject *KSHARK_ERROR = NULL;
+static PyObject *TRACECRUNCHER_ERROR = NULL;
+
+static PyObject *method_open(PyObject *self, PyObject *args,
+					     PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	char *fname = NULL;
+
+	static char *kwlist[] = {"fname", NULL};
+	if(!PyArg_ParseTupleAndKeywords(args,
+					kwargs,
+					"s",
+					kwlist,
+					&fname)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	if (!kshark_open(kshark_ctx, fname))
+		return Py_False;
+
+	return Py_True;
+}
+
+static PyObject* method_close(PyObject* self, PyObject* noarg)
+{
+	struct kshark_context *kshark_ctx = NULL;
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	kshark_close(kshark_ctx);
+
+	Py_RETURN_NONE;
+}
+
+static int compare(const void *a, const void *b)
+{
+	int a_i, b_i;
+
+	a_i = *(const int *) a;
+	b_i = *(const int *) b;
+
+	if (a_i > b_i)
+		return +1;
+
+	if (a_i < b_i)
+		return -1;
+
+	return 0;
+}
+
+static PyObject* method_get_tasks(PyObject* self, PyObject* noarg)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	const char *comm;
+	int *pids;
+	ssize_t i, n;
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	n = kshark_get_task_pids(kshark_ctx, &pids);
+	if (n == 0) {
+		PyErr_SetString(KSHARK_ERROR,
+				"Failed to retrieve the PID-s of the tasks");
+		return NULL;
+	}
+
+	qsort(pids, n, sizeof(*pids), compare);
+
+	PyObject *tasks, *pid_list, *pid_val;
+
+	tasks = PyDict_New();
+	for (i = 0; i < n; ++i) {
+		comm = tep_data_comm_from_pid(kshark_ctx->pevent, pids[i]);
+		pid_val = PyLong_FromLong(pids[i]);
+		pid_list = PyDict_GetItemString(tasks, comm);
+		if (!pid_list) {
+			pid_list = PyList_New(1);
+			PyList_SET_ITEM(pid_list, 0, pid_val);
+			PyDict_SetItemString(tasks, comm, pid_list);
+		} else {
+			PyList_Append(pid_list, pid_val);
+		}
+	}
+
+	return tasks;
+}
+
+static PyObject *method_register_plugin(PyObject *self, PyObject *args,
+							PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	char *plugin, *lib_file;
+	int ret;
+
+	static char *kwlist[] = {"plugin", NULL};
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "s",
+					 kwlist,
+					 &plugin)) {
+		return NULL;
+	}
+
+	if (asprintf(&lib_file, "%s/plugin-%s.so", KS_PLUGIN_DIR, plugin) < 0) {
+		KS_MEM_ERROR
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	ret = kshark_register_plugin(kshark_ctx, lib_file);
+	free(lib_file);
+	if (ret < 0) {
+		PyErr_Format(KSHARK_ERROR,
+			     "libshark failed to load plugin '%s'",
+			     plugin);
+		return NULL;
+	}
+
+	if (kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_INIT) < 0) {
+		PyErr_SetString(KSHARK_ERROR,
+				"libshark failed to handle its plugins");
+		return NULL;
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *method_new_session_file(PyObject *self, PyObject *args,
+							 PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct kshark_config_doc *session;
+	struct kshark_config_doc *filters;
+	struct kshark_config_doc *markers;
+	struct kshark_config_doc *model;
+	struct kshark_config_doc *file;
+	struct kshark_trace_histo histo;
+	const char *session_file, *data_file;
+
+	static char *kwlist[] = {"data_file", "session_file", NULL};
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "ss",
+					 kwlist,
+					 &data_file,
+					 &session_file)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	session = kshark_config_new("kshark.config.session",
+				    KS_CONFIG_JSON);
+
+	file = kshark_export_trace_file(data_file, KS_CONFIG_JSON);
+	kshark_config_doc_add(session, "Data", file);
+
+	filters = kshark_export_all_filters(kshark_ctx, KS_CONFIG_JSON);
+	kshark_config_doc_add(session, "Filters", filters);
+
+	ksmodel_init(&histo);
+	model = kshark_export_model(&histo, KS_CONFIG_JSON);
+	kshark_config_doc_add(session, "Model", model);
+
+	markers = kshark_config_new("kshark.config.markers", KS_CONFIG_JSON);
+	kshark_config_doc_add(session, "Markers", markers);
+
+	kshark_save_config_file(session_file, session);
+	kshark_free_config_doc(session);
+
+	Py_RETURN_NONE;
+}
+
+static PyMethodDef ksharkpy_methods[] = {
+	{"open",
+	 (PyCFunction) method_open,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Open trace data file"
+	},
+	{"close",
+	 (PyCFunction) method_close,
+	 METH_NOARGS,
+	 "Close trace data file"
+	},
+	{"get_tasks",
+	 (PyCFunction) method_get_tasks,
+	 METH_NOARGS,
+	 "Get all tasks recorded in a trace file"
+	},
+	{"register_plugin",
+	 (PyCFunction) method_register_plugin,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Load a plugin"
+	},
+	{"new_session_file",
+	 (PyCFunction) method_new_session_file,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Create new session description file"
+	},
+	{NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef ksharkpy_module = {
+	PyModuleDef_HEAD_INIT,
+	"ksharkpy",
+	"",
+	-1,
+	ksharkpy_methods
+};
+
+PyMODINIT_FUNC PyInit_ksharkpy(void)
+{
+	PyObject *module = PyModule_Create(&ksharkpy_module);
+
+	KSHARK_ERROR = PyErr_NewException("tracecruncher.ksharkpy.ks_error",
+					  NULL, NULL);
+	PyModule_AddObject(module, "ks_error", KSHARK_ERROR);
+
+	TRACECRUNCHER_ERROR = PyErr_NewException("tracecruncher.tc_error",
+						 NULL, NULL);
+	PyModule_AddObject(module, "tc_error", TRACECRUNCHER_ERROR);
+
+	return module;
+}
diff --git a/tracecruncher/__init__.py b/tracecruncher/__init__.py
new file mode 100644
index 0000000..e69de29
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] Refactor the part of the interface that relies on libtraceevent
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 1/5] Refactor the part of the interface that relies on libkshark Yordan Karadzhov (VMware)
@ 2019-12-12  9:02 ` Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 3/5] Refactor NumPy based data wrapper Yordan Karadzhov (VMware)
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

The part of the interface that relies on libtraceevent gets
re-implemented as an extension called "tracecruncher.ftracepy".
The new extension gets build together with the previously
implemented "tracecruncher.ksharkpy" extension.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 setup.py       |  11 ++-
 src/common.h   |   1 +
 src/ftracepy.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+), 1 deletion(-)
 create mode 100644 src/ftracepy.c

diff --git a/setup.py b/setup.py
index 6a1d2e8..dfe1d00 100644
--- a/setup.py
+++ b/setup.py
@@ -13,6 +13,8 @@ from Cython.Build import cythonize
 
 def main():
     kshark_path = '/usr/local/lib/kernelshark'
+    traceevent_path = '/usr/local/lib/traceevent/'
+    tracecmd_path = '/usr/local/lib/trace-cmd/'
 
     module_ks = Extension('tracecruncher.ksharkpy',
                           sources=['src/ksharkpy.c'],
@@ -25,6 +27,13 @@ def main():
                               ],
                           )
 
+    module_ft = Extension('tracecruncher.ftracepy',
+                          sources=['src/ftracepy.c'],
+                          library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+                          runtime_library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+                          libraries=['kshark', 'traceevent', 'tracecmd'],
+                          )
+
     setup(name='tracecruncher',
           version='0.1.0',
           description='NumPy based interface for accessing tracing data in Python.',
@@ -33,7 +42,7 @@ def main():
           url='https://github.com/vmware/trace-cruncher',
           license='LGPL-2.1',
           packages=find_packages(),
-          ext_modules=[module_ks],
+          ext_modules=[module_ks, module_ft],
           classifiers=[
               'Development Status :: 3 - Alpha',
               'Programming Language :: Python :: 3',
diff --git a/src/common.h b/src/common.h
index d7d355a..632e17a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -9,6 +9,7 @@
 
 #define TRACECRUNCHER_ERROR	tracecruncher_error
 #define KSHARK_ERROR		kshark_error
+#define FTRACE_ERROR		ftrace_error
 
 #define KS_INIT_ERROR \
 	PyErr_SetString(KSHARK_ERROR, "libshark failed to initialize");
diff --git a/src/ftracepy.c b/src/ftracepy.c
new file mode 100644
index 0000000..e23b875
--- /dev/null
+++ b/src/ftracepy.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+ */
+
+// Python
+#include <Python.h>
+
+// trace-cmd
+#include "trace-cmd/trace-cmd.h"
+
+// KernelShark
+#include "kernelshark/libkshark.h"
+#include "kernelshark/libkshark-tepdata.h"
+
+// trace-cruncher
+#include "common.h"
+
+static PyObject *KSHARK_ERROR = NULL;
+static PyObject *FTRACE_ERROR = NULL;
+
+static PyObject *method_event_id(PyObject *self, PyObject *args,
+						 PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct tep_event *event;
+	const char *system, *name;
+
+	static char *kwlist[] = {"system", "event", NULL};
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "ss",
+					 kwlist,
+					 &system,
+					 &name)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	event = tep_find_event_by_name(kshark_ctx->pevent, system, name);
+	if (!event) {
+		PyErr_Format(FTRACE_ERROR,
+			     "Failed to find event '%s/%s'",
+			     system, name);
+	}
+
+	return PyLong_FromLong(event->id);
+}
+
+static PyObject *method_read_event_field(PyObject *self, PyObject *args,
+							 PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct tep_format_field *evt_field;
+	struct tep_record *record;
+	struct tep_event *event;
+	unsigned long long val;
+	const char *field;
+	uint64_t offset;
+	int event_id, ret;
+
+	static char *kwlist[] = {"offset", "event_id", "field", NULL};
+	if(!PyArg_ParseTupleAndKeywords(args,
+					kwargs,
+					"Lis",
+					kwlist,
+					&offset,
+					&event_id,
+					&field)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	event = tep_find_event(kshark_ctx->pevent, event_id);
+	if (!event) {
+		PyErr_Format(FTRACE_ERROR,
+			     "Failed to find event '%i'",
+			     event_id);
+		return NULL;
+	}
+
+	evt_field = tep_find_any_field(event, field);
+	if (!evt_field) {
+		PyErr_Format(FTRACE_ERROR,
+			     "Failed to find field '%s' of event '%i'",
+			     field, event_id);
+		return NULL;
+	}
+
+	record = tracecmd_read_at(kshark_ctx->handle, offset, NULL);
+	if (!record) {
+		PyErr_Format(FTRACE_ERROR,
+			     "Failed to read record at offset '%i'",
+			     offset);
+		return NULL;
+	}
+
+	ret = tep_read_number_field(evt_field, record->data, &val);
+	free_record(record);
+
+	if (ret != 0) {
+		PyErr_Format(FTRACE_ERROR,
+			     "Failed to read field '%s' of event '%i'",
+			     field, event_id);
+		return NULL;
+	}
+
+	return PyLong_FromLong(val);
+}
+
+static PyObject *method_get_function(PyObject *self, PyObject *args,
+						     PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	unsigned long long address;
+	const char *func;
+
+	static char *kwlist[] = {"address"};
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "i",
+					 kwlist,
+					 &address)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	func = tep_find_function(kshark_ctx->pevent, address);
+	if (!func)
+		Py_RETURN_NONE;
+
+	return PyUnicode_FromString(func);
+}
+
+static PyObject *method_map_instruction_address(PyObject *self, PyObject *args,
+								PyObject *kwargs)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct tracecmd_proc_addr_map *mem_map;
+	unsigned long long proc_addr, obj_addr;
+	int pid;
+	PyObject *ret;
+
+	static char *kwlist[] = {"pid", "proc_addr"};
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "iL",
+					 kwlist,
+					 &pid,
+					 &proc_addr)) {
+		return NULL;
+	}
+
+	if (!kshark_instance(&kshark_ctx)) {
+		KS_INIT_ERROR
+		return NULL;
+	}
+
+	mem_map = tracecmd_search_task_map(kshark_ctx->handle,
+					   pid, proc_addr);
+
+	if (!mem_map)
+		Py_RETURN_NONE;
+
+	ret = PyDict_New();
+
+	PyDict_SetItemString(ret, "obj_file",
+			     PyUnicode_FromString(mem_map->lib_name));
+
+	obj_addr = proc_addr - mem_map->start;
+	PyDict_SetItemString(ret, "address", PyLong_FromLong(obj_addr));
+
+	return ret;
+}
+
+static PyMethodDef ftracepy_methods[] = {
+	{"event_id",
+	 (PyCFunction) method_event_id,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Get the Id of the event from its name"
+	},
+	{"read_event_field",
+	 (PyCFunction) method_read_event_field,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Get the value of an event field having a given name"
+	},
+	{"get_function",
+	 (PyCFunction) method_get_function,
+	 METH_VARARGS | METH_KEYWORDS,
+	 ""
+	},
+	{"map_instruction_address",
+	 (PyCFunction) method_map_instruction_address,
+	 METH_VARARGS | METH_KEYWORDS,
+	 ""
+	},
+	{NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef ftracepy_module = {
+	PyModuleDef_HEAD_INIT,
+	"ftracepy",
+	"",
+	-1,
+	ftracepy_methods
+};
+
+PyMODINIT_FUNC PyInit_ftracepy(void)
+{
+	PyObject *module =  PyModule_Create(&ftracepy_module);
+
+	KSHARK_ERROR = PyErr_NewException("tracecruncher.ftracepy.ks_error",
+					  NULL, NULL);
+	PyModule_AddObject(module, "ks_error", KSHARK_ERROR);
+
+	FTRACE_ERROR = PyErr_NewException("tracecruncher.ftracepy.ft_error",
+					  NULL, NULL);
+	PyModule_AddObject(module, "ft_error", FTRACE_ERROR);
+
+	return module;
+}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] Refactor NumPy based data wrapper
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 1/5] Refactor the part of the interface that relies on libkshark Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 2/5] Refactor the part of the interface that relies on libtraceevent Yordan Karadzhov (VMware)
@ 2019-12-12  9:02 ` Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 4/5] Add "utils" Yordan Karadzhov (VMware)
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

The data wrapper is the only thing that remains being built with Cython.
It is now a subpackage called "tracecruncher.datawrapper".

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 setup.py            |  10 ++-
 src/datawrapper.pyx | 201 ++++++++++++++++++++++++++++++++++++++++++++
 src/trace2matrix.c  |  29 +++++++
 3 files changed, 239 insertions(+), 1 deletion(-)
 create mode 100644 src/datawrapper.pyx
 create mode 100644 src/trace2matrix.c

diff --git a/setup.py b/setup.py
index dfe1d00..5a07710 100644
--- a/setup.py
+++ b/setup.py
@@ -16,6 +16,14 @@ def main():
     traceevent_path = '/usr/local/lib/traceevent/'
     tracecmd_path = '/usr/local/lib/trace-cmd/'
 
+    cythonize('src/datawrapper.pyx')
+    module_data = Extension('tracecruncher.datawrapper',
+                            sources=['src/datawrapper.c'],
+                            library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+                            runtime_library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+                            libraries=['kshark', 'traceevent', 'tracecmd']
+                            )
+
     module_ks = Extension('tracecruncher.ksharkpy',
                           sources=['src/ksharkpy.c'],
                           library_dirs=[kshark_path],
@@ -42,7 +50,7 @@ def main():
           url='https://github.com/vmware/trace-cruncher',
           license='LGPL-2.1',
           packages=find_packages(),
-          ext_modules=[module_ks, module_ft],
+          ext_modules=[module_data, module_ks, module_ft],
           classifiers=[
               'Development Status :: 3 - Alpha',
               'Programming Language :: Python :: 3',
diff --git a/src/datawrapper.pyx b/src/datawrapper.pyx
new file mode 100644
index 0000000..070d4e4
--- /dev/null
+++ b/src/datawrapper.pyx
@@ -0,0 +1,201 @@
+"""
+SPDX-License-Identifier: LGPL-2.1
+
+Copyright 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+"""
+
+import ctypes
+
+# Import the Python-level symbols of numpy
+import numpy as np
+# Import the C-level symbols of numpy
+cimport numpy as np
+
+import json
+
+from libcpp cimport bool
+
+from libc.stdlib cimport free
+
+from cpython cimport PyObject, Py_INCREF
+
+from libc cimport stdint
+ctypedef stdint.int16_t int16_t
+ctypedef stdint.uint16_t uint16_t
+ctypedef stdint.int32_t int32_t
+ctypedef stdint.uint32_t uint32_t
+ctypedef stdint.int64_t int64_t
+ctypedef stdint.uint64_t uint64_t
+
+cdef extern from 'numpy/ndarraytypes.h':
+    int NPY_ARRAY_CARRAY
+    
+# Numpy must be initialized!!!
+np.import_array()
+
+cdef extern from 'trace2matrix.c':
+    ssize_t trace2matrix(uint64_t **offset_array,
+			 uint16_t **cpu_array,
+			 uint64_t **ts_array,
+			 uint16_t **pid_array,
+			 int **event_array)
+
+data_column_types = {
+    'cpu': np.NPY_UINT16,
+    'pid': np.NPY_UINT16,
+    'event': np.NPY_INT,
+    'offset': np.NPY_UINT64,
+    'time': np.NPY_UINT64
+    }
+
+cdef class KsDataWrapper:
+    cdef int item_size
+    cdef int data_size
+    cdef int data_type
+    cdef void* data_ptr
+
+    cdef init(self, int data_type,
+                    int data_size,
+                    int item_size,
+                    void* data_ptr):
+        """ This initialization cannot be done in the constructor because
+            we use C-level arguments.
+        """
+        self.item_size = item_size
+        self.data_size = data_size
+        self.data_type = data_type
+        self.data_ptr = data_ptr
+
+    def __array__(self):
+        """ Here we use the __array__ method, that is called when numpy
+            tries to get an array from the object.
+        """
+        cdef np.npy_intp shape[1]
+        shape[0] = <np.npy_intp> self.data_size
+
+        ndarray = np.PyArray_New(np.ndarray,
+                                 1, shape,
+                                 self.data_type,
+                                 NULL,
+                                 self.data_ptr,
+                                 self.item_size,
+                                 NPY_ARRAY_CARRAY,
+                                 <object>NULL)
+
+        return ndarray
+
+    def __dealloc__(self):
+        """ Free the data. This is called by Python when all the references to
+            the object are gone.
+        """
+        free(<void*>self.data_ptr)
+
+
+def load(ofst_data=True, cpu_data=True, ts_data=True,
+         pid_data=True, evt_data=True):
+    """ Python binding of the 'kshark_load_data_matrix' function that does not
+        copy the data. The input parameters can be used to avoid loading the
+        data from the unnecessary fields.
+    """
+    cdef uint64_t *ofst_c
+    cdef uint16_t *cpu_c
+    cdef uint64_t *ts_c
+    cdef uint16_t *pid_c
+    cdef int *evt_c
+
+    cdef np.ndarray ofst
+    cdef np.ndarray cpu
+    cdef np.ndarray ts
+    cdef np.ndarray pid
+    cdef np.ndarray evt
+
+    if not ofst_data:
+        ofst_c = NULL
+
+    if not cpu_data:
+        cpu_c = NULL
+
+    if not ts_data:
+        ts_c = NULL
+
+    if not pid_data:
+        pid_c = NULL
+
+    if not evt_data:
+        evt_c = NULL
+
+    data_dict = {}
+
+    cdef ssize_t size
+
+    size = trace2matrix(&ofst_c, &cpu_c, &ts_c, &pid_c, &evt_c)
+    if size <= 0:
+        raise Exception('No data has been loaded.')
+
+    if cpu_data:
+        column = 'cpu'
+        array_wrapper_cpu = KsDataWrapper()
+        array_wrapper_cpu.init(data_type=data_column_types[column],
+                               data_size=size,
+                               item_size=0,
+                               data_ptr=<void *> cpu_c)
+
+        cpu = np.array(array_wrapper_cpu, copy=False)
+        cpu.base = <PyObject *> array_wrapper_cpu
+        data_dict.update({column: cpu})
+        Py_INCREF(array_wrapper_cpu)
+
+    if pid_data:
+        column = 'pid'
+        array_wrapper_pid = KsDataWrapper()
+        array_wrapper_pid.init(data_type=data_column_types[column],
+                               data_size=size,
+                               item_size=0,
+                               data_ptr=<void *>pid_c)
+
+        pid = np.array(array_wrapper_pid, copy=False)
+        pid.base = <PyObject *> array_wrapper_pid
+        data_dict.update({column: pid})
+        Py_INCREF(array_wrapper_pid)
+
+    if evt_data:
+        column = 'event'
+        array_wrapper_evt = KsDataWrapper()
+        array_wrapper_evt.init(data_type=data_column_types[column],
+                               data_size=size,
+                               item_size=0,
+                               data_ptr=<void *>evt_c)
+
+        evt = np.array(array_wrapper_evt, copy=False)
+        evt.base = <PyObject *> array_wrapper_evt
+        data_dict.update({column: evt})
+        Py_INCREF(array_wrapper_evt)
+
+    if ofst_data:
+        column = 'offset'
+        array_wrapper_ofst = KsDataWrapper()
+        array_wrapper_ofst.init(data_type=data_column_types[column],
+                                data_size=size,
+                                item_size=0,
+                                data_ptr=<void *> ofst_c)
+
+
+        ofst = np.array(array_wrapper_ofst, copy=False)
+        ofst.base = <PyObject *> array_wrapper_ofst
+        data_dict.update({column: ofst})
+        Py_INCREF(array_wrapper_ofst)
+        
+    if ts_data:
+        column = 'time'
+        array_wrapper_ts = KsDataWrapper()
+        array_wrapper_ts.init(data_type=data_column_types[column],
+                              data_size=size,
+                              item_size=0,
+                              data_ptr=<void *> ts_c)
+
+        ts = np.array(array_wrapper_ts, copy=False)
+        ts.base = <PyObject *> array_wrapper_ts
+        data_dict.update({column: ts})
+        Py_INCREF(array_wrapper_ts)
+
+    return data_dict
diff --git a/src/trace2matrix.c b/src/trace2matrix.c
new file mode 100644
index 0000000..aaf8322
--- /dev/null
+++ b/src/trace2matrix.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright 2019 VMware Inc, Yordan Karadzhov <ykaradzhov@vmware.com>
+ */
+
+// KernelShark
+#include "kernelshark/libkshark.h"
+
+ssize_t trace2matrix(uint64_t **offset_array,
+		     uint16_t **cpu_array,
+		     uint64_t **ts_array,
+		     uint16_t **pid_array,
+		     int **event_array)
+{
+	struct kshark_context *kshark_ctx = NULL;
+	ssize_t total = 0;
+
+	if (!kshark_instance(&kshark_ctx))
+		return -1;
+
+	total = kshark_load_data_matrix(kshark_ctx, offset_array,
+						    cpu_array,
+						    ts_array,
+						    pid_array,
+						    event_array);
+
+	return total;
+}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] Add "utils"
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
                   ` (2 preceding siblings ...)
  2019-12-12  9:02 ` [PATCH 3/5] Refactor NumPy based data wrapper Yordan Karadzhov (VMware)
@ 2019-12-12  9:02 ` Yordan Karadzhov (VMware)
  2019-12-12  9:02 ` [PATCH 5/5] Adapt the sched_wakeup.py example script to use the new tracecruncher module Yordan Karadzhov (VMware)
  2019-12-31 18:37 ` [PATCH 0/5] Build trace-cruncher as Python pakage Douglas Raillard
  5 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

Place the rest of the code, that is pure Python in tracecrunche/utils.py

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 tracecruncher/utils.py | 54 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 tracecruncher/utils.py

diff --git a/tracecruncher/utils.py b/tracecruncher/utils.py
new file mode 100644
index 0000000..f785c01
--- /dev/null
+++ b/tracecruncher/utils.py
@@ -0,0 +1,54 @@
+"""
+SPDX-License-Identifier: LGPL-2.1
+
+Copyright 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+"""
+
+import json
+
+from . import datawrapper as dw
+from . import ksharkpy as ks
+
+def size(data):
+    """ Get the number of trace records.
+    """
+    for key in dw.data_column_types:
+        if data[key] is not None:
+            return data[key].size
+
+    raise Exception('Data size is unknown.')
+
+def save_session(session, s):
+    """ Save a KernelShark session description of a JSON file.
+    """
+    s.seek(0)
+    json.dump(session, s, indent=4)
+    s.truncate()
+
+
+def new_gui_session(fname, sname):
+    """ Generate and save a default KernelShark session description
+        file (JSON).
+    """
+    ks.new_session_file(fname, sname)
+
+    with open(sname, 'r+') as s:
+        session = json.load(s)
+
+        session['Filters']['filter mask'] = 7
+        session['CPUPlots'] = []
+        session['TaskPlots'] = []
+        session['Splitter'] = [1, 1]
+        session['MainWindow'] = [1200, 800]
+        session['ViewTop'] = 0
+        session['ColorScheme'] = 0.75
+        session['Model']['bins'] = 1000
+
+        session['Markers']['markA'] = {}
+        session['Markers']['markA']['isSet'] = False
+        session['Markers']['markB'] = {}
+        session['Markers']['markB']['isSet'] = False
+        session['Markers']['Active'] = 'A'
+
+        save_session(session, s)
+
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] Adapt the sched_wakeup.py example script to use the new tracecruncher module
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
                   ` (3 preceding siblings ...)
  2019-12-12  9:02 ` [PATCH 4/5] Add "utils" Yordan Karadzhov (VMware)
@ 2019-12-12  9:02 ` Yordan Karadzhov (VMware)
  2019-12-31 18:37 ` [PATCH 0/5] Build trace-cruncher as Python pakage Douglas Raillard
  5 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2019-12-12  9:02 UTC (permalink / raw)
  To: linux-trace-devel
  Cc: rostedt, Valentin.Schneider, douglas.raillard, Yordan Karadzhov (VMware)

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 examples/sched_wakeup.py | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/examples/sched_wakeup.py b/examples/sched_wakeup.py
index 52f2688..41e0c9c 100755
--- a/examples/sched_wakeup.py
+++ b/examples/sched_wakeup.py
@@ -15,18 +15,18 @@ import matplotlib.pyplot as plt
 import scipy.stats as st
 import numpy as np
 
-from ksharksetup import setup
-# Always call setup() before importing ksharkpy!!!
-setup()
+import tracecruncher.datawrapper as dw
+import tracecruncher.ksharkpy as ks
+import tracecruncher.ftracepy as ft
+import tracecruncher.utils as tc
 
-import ksharkpy as ks
 # Get the name of the user program.
 if len(sys.argv) >= 2:
     fname = str(sys.argv[1])
 else:
     fname = input('choose a trace file: ')
 
-status = ks.open_file(fname)
+status = ks.open(fname)
 if not status:
     print ("Failed to open file ", fname)
     sys.exit()
@@ -35,7 +35,7 @@ ks.register_plugin('reg_pid')
 
 # We do not need the Process Ids of the records.
 # Do not load the "pid" data.
-data = ks.load_data(pid_data=False)
+data = dw.load(pid_data=False)
 tasks = ks.get_tasks()
 
 # Get the name of the user program.
@@ -48,8 +48,8 @@ else:
 task_pid = tasks[prog_name][0]
 
 # Get the Event Ids of the sched_switch and sched_waking events.
-ss_eid = ks.event_id('sched', 'sched_switch')
-w_eid = ks.event_id('sched', 'sched_waking')
+ss_eid = ft.event_id('sched', 'sched_switch')
+w_eid = ft.event_id('sched', 'sched_waking')
 
 # Gey the size of the data.
 i = data['offset'].size
@@ -60,7 +60,7 @@ delta_max = i_ss_max = i_sw_max = 0
 while i > 0:
     i = i - 1
     if data['event'][i] == ss_eid:
-        next_pid = ks.read_event_field(offset=data['offset'][i],
+        next_pid = ft.read_event_field(offset=data['offset'][i],
                                        event_id=ss_eid,
                                        field='next_pid')
 
@@ -77,9 +77,9 @@ while i > 0:
                         break
 
                 if data['event'][i] == ss_eid:
-                    next_pid = ks.read_event_field(offset=data['offset'][i],
-                                       event_id=ss_eid,
-                                       field='next_pid')
+                    next_pid = ft.read_event_field(offset=data['offset'][i],
+                                                   event_id=ss_eid,
+                                                   field='next_pid')
                     if next_pid == task_pid:
                         # Second sched_switch for the same task. ?
                         time_ss = data['time'][i]
@@ -89,7 +89,7 @@ while i > 0:
                     continue
 
                 if (data['event'][i] == w_eid):
-                    waking_pid = ks.read_event_field(offset=data['offset'][i],
+                    waking_pid = ft.read_event_field(offset=data['offset'][i],
                                                      event_id=w_eid,
                                                      field='pid')
 
@@ -120,7 +120,7 @@ ax.hist(dt, bins=(100), histtype='step')
 plt.show()
 
 sname = 'sched.json'
-ks.new_session(fname, sname)
+tc.new_gui_session(fname, sname)
 
 with open(sname, 'r+') as s:
     session = json.load(s)
@@ -143,6 +143,6 @@ with open(sname, 'r+') as s:
 
     session['ViewTop'] = int(i_sw_max) - 5
 
-    ks.save_session(session, s)
+    tc.save_session(session, s)
 
 ks.close()
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/5] Build trace-cruncher as Python pakage
  2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
                   ` (4 preceding siblings ...)
  2019-12-12  9:02 ` [PATCH 5/5] Adapt the sched_wakeup.py example script to use the new tracecruncher module Yordan Karadzhov (VMware)
@ 2019-12-31 18:37 ` Douglas Raillard
  2020-01-07 16:59   ` Yordan Karadzhov (VMware)
  5 siblings, 1 reply; 8+ messages in thread
From: Douglas Raillard @ 2019-12-31 18:37 UTC (permalink / raw)
  To: Yordan Karadzhov (VMware), linux-trace-devel
  Cc: rostedt, Valentin Schneider, nd

Hi Yordan,

Finally got around to trying trace-cruncher. I've rediscovered how much I hated C build
systems issues in general, so here is the outcome of the first day of battle :-)

kernelshark bits:
* kernelshark build system seems to ignore the standard CMAKE_INSTALL_PREFIX
  but uses _INSTALL_PREFIX instead, might be worth aligning with the documented
  standard stuff of CMake if that makes sense.
* _INSTALL_PREFIX is used for almost everything, except a polkit file that is copied
  to /usr/share/polkit-1 regardless of _INSTALL_PREFIX, which makes installing as
  non root fail.

Now trace-cruncher-specific bits:
* Building kernelshark gives shared objects with .so.X.Y.Z file names, but GCC
  wants to link against .so
* There are some hardcoded paths to /usr/local/ in setup.py. They don't seem
  to break user-given include paths but it would probably be a good idea to
  make that somewhat parametric.
* libkshark-input.h does not seem to exist but is used by ksharkpy.c. I'm not sure
  if I used the wrong version of something or if that's a genuine issue.

Here is the command I used to try to build trace-cruncher in a venv with
numpy and cython installed:
$ pip install . --global-option=build_ext --global-option='-Itrace-cmd/install/include' --global-option='-Ltrace-cmd/install/lib/kernelshark:trace-cmd/install/lib/trace-cmd:trace-cmd/install/lib/traceevent'

I've pushed some WIP commits on top of your series on my fork if you
want to get a look at them:

Branch: refactor
remote: https://github.com/douglas-raillard-arm/trace-cruncher.git
https://github.com/douglas-raillard-arm/trace-cruncher/commits/refactor

For the sake of reproducibility until things become stable, it might be a good idea
to maintain a WIP branch with submodules/subtrees for trace-cmd in the right version
in trace-cruncher repo, and the series applied, so we don't have to jugle with the
ML lore to get mbox plus other patches from the repo itself etc. Once we have that,
we can easily include a script that calls all the build systems involved and install all the
required bits in a venv, without polluting system-wide locations, and progressively
turn that into a standalone setup.py (or the nearest approximation of that we
manage to make).

PS: apologies for the extra new lines and lack of reply markers,
Office 365 webmail does not seem to play very nicely with plain text ...

Cheers,
Douglas

From: Yordan Karadzhov (VMware) <y.karadz@gmail.com>

Sent: 12 December 2019 09:02

To: linux-trace-devel@vger.kernel.org <linux-trace-devel@vger.kernel.org>

Cc: rostedt@goodmis.org <rostedt@goodmis.org>; Valentin Schneider <Valentin.Schneider@arm.com>; Douglas Raillard <Douglas.Raillard@arm.com>; Yordan Karadzhov (VMware) <y.karadz@gmail.com>

Subject: [PATCH 0/5] Build trace-cruncher as Python pakage




This patch-set is an attempt to restructure the project and to make it

build as a native Python package. Although it looks like a complete

rewrite, this is essentially just a switching from using Cython to using

directly the C API of Python. Cython is still being used but only for

the implementation of the NumPy data wrapper. The new package has its

own stand-alone build system (very primitive for the moment) that is

completely decoupled from the existing build system used by tracecruncher.

In order to build and install the new package do:



sudo python setup.py install --record files.txt



The patch-set does not  remove the old implementation yet. This will

happen in another successive patch-set.



Please review as careful as possible!



Yordan Karadzhov (VMware) (5):

  Refactor the part of the interface that relies on libkshark

  Refactor the part of the interface that relies on libtraceevent

  Refactor NumPy based data wrapper

  Add "utils"

  Adapt the sched_wakeup.py example script to use the new tracecruncher

    module



 examples/sched_wakeup.py  |  30 ++---

 setup.py                  |  61 +++++++++

 src/common.h              |  20 +++

 src/datawrapper.pyx       | 201 ++++++++++++++++++++++++++++

 src/ftracepy.c            | 234 +++++++++++++++++++++++++++++++++

 src/ksharkpy.c            | 268 ++++++++++++++++++++++++++++++++++++++

 src/trace2matrix.c        |  29 +++++

 tracecruncher/__init__.py |   0

 tracecruncher/utils.py    |  54 ++++++++

 9 files changed, 882 insertions(+), 15 deletions(-)

 create mode 100644 setup.py

 create mode 100644 src/common.h

 create mode 100644 src/datawrapper.pyx

 create mode 100644 src/ftracepy.c

 create mode 100644 src/ksharkpy.c

 create mode 100644 src/trace2matrix.c

 create mode 100644 tracecruncher/__init__.py

 create mode 100644 tracecruncher/utils.py



--

2.20.1



IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/5] Build trace-cruncher as Python pakage
  2019-12-31 18:37 ` [PATCH 0/5] Build trace-cruncher as Python pakage Douglas Raillard
@ 2020-01-07 16:59   ` Yordan Karadzhov (VMware)
  0 siblings, 0 replies; 8+ messages in thread
From: Yordan Karadzhov (VMware) @ 2020-01-07 16:59 UTC (permalink / raw)
  To: Douglas Raillard, linux-trace-devel; +Cc: rostedt, Valentin Schneider, nd

Hi Douglas,

Happy new year!
Thanks a lot for trying trace-cruncher and providing us with useful 
feedback!

On 31.12.19 г. 20:37 ч., Douglas Raillard wrote:
> Hi Yordan,
> 
> Finally got around to trying trace-cruncher. I've rediscovered how much I hated C build
> systems issues in general, so here is the outcome of the first day of battle :-)
> 
> kernelshark bits:
> * kernelshark build system seems to ignore the standard CMAKE_INSTALL_PREFIX
>    but uses _INSTALL_PREFIX instead, might be worth aligning with the documented
>    standard stuff of CMake if that makes sense.
> * _INSTALL_PREFIX is used for almost everything, except a polkit file that is copied
>    to /usr/share/polkit-1 regardless of _INSTALL_PREFIX, which makes installing as
>    non root fail.
> 
> Now trace-cruncher-specific bits:
> * Building kernelshark gives shared objects with .so.X.Y.Z file names, but GCC
>    wants to link against .so
> * There are some hardcoded paths to /usr/local/ in setup.py. They don't seem
>    to break user-given include paths but it would probably be a good idea to
>    make that somewhat parametric.
> * libkshark-input.h does not seem to exist but is used by ksharkpy.c. I'm not sure
>    if I used the wrong version of something or if that's a genuine issue.
> 

I am going to send a second version of the patch-set that tries to 
address some of the problems you found. This second version of the 
patches goes a bit further and simplifies/automates the build process 
for the user. Now you only have to do:

 > make
 > sudo make install

and that's all. You also have "make clean" and "make uninstall". I hope 
this will fix the problems you reported above.

> Here is the command I used to try to build trace-cruncher in a venv with
> numpy and cython installed:
> $ pip install . --global-option=build_ext --global-option='-Itrace-cmd/install/include' --global-option='-Ltrace-cmd/install/lib/kernelshark:trace-cmd/install/lib/trace-cmd:trace-cmd/install/lib/traceevent'
> 
> I've pushed some WIP commits on top of your series on my fork if you
> want to get a look at them:
> 
> Branch: refactor
> remote: https://github.com/douglas-raillard-arm/trace-cruncher.git
> https://github.com/douglas-raillard-arm/trace-cruncher/commits/refactor
>

All new patches are available here:
https://github.com/vmware/trace-cruncher/tree/refactoring_WIP (branch 
"refactoring_WIP")

> For the sake of reproducibility until things become stable, it might be a good idea
> to maintain a WIP branch with submodules/subtrees for trace-cmd in the right version
> in trace-cruncher repo, and the series applied, so we don't have to jugle with the
> ML lore to get mbox plus other patches from the repo itself etc. Once we have that,
> we can easily include a script that calls all the build systems involved and install all the
> required bits in a venv, without polluting system-wide locations, and progressively
> turn that into a standalone setup.py (or the nearest approximation of that we
> manage to make).

In v2 I am trying to address this, partially by automating the patching 
and build of trace-cmd and partially by making all those patched 
libraries part of the package itself (exploiting some linker magic). 
However, your solution to use venv is probably by fare more common. It 
will be great if we can have some discussion here and decide which of 
the two solutions is the best.

Once again, thanks for helping us!
cheers,
Yordan

> 
> PS: apologies for the extra new lines and lack of reply markers,
> Office 365 webmail does not seem to play very nicely with plain text ...
> 
> Cheers,
> Douglas
> 
> From: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
> 
> Sent: 12 December 2019 09:02
> 
> To: linux-trace-devel@vger.kernel.org <linux-trace-devel@vger.kernel.org>
> 
> Cc: rostedt@goodmis.org <rostedt@goodmis.org>; Valentin Schneider <Valentin.Schneider@arm.com>; Douglas Raillard <Douglas.Raillard@arm.com>; Yordan Karadzhov (VMware) <y.karadz@gmail.com>
> 
> Subject: [PATCH 0/5] Build trace-cruncher as Python pakage
> 
> 
> 
> 
> This patch-set is an attempt to restructure the project and to make it
> 
> build as a native Python package. Although it looks like a complete
> 
> rewrite, this is essentially just a switching from using Cython to using
> 
> directly the C API of Python. Cython is still being used but only for
> 
> the implementation of the NumPy data wrapper. The new package has its
> 
> own stand-alone build system (very primitive for the moment) that is
> 
> completely decoupled from the existing build system used by tracecruncher.
> 
> In order to build and install the new package do:
> 
> 
> 
> sudo python setup.py install --record files.txt
> 
> 
> 
> The patch-set does not  remove the old implementation yet. This will
> 
> happen in another successive patch-set.
> 
> 
> 
> Please review as careful as possible!
> 
> 
> 
> Yordan Karadzhov (VMware) (5):
> 
>    Refactor the part of the interface that relies on libkshark
> 
>    Refactor the part of the interface that relies on libtraceevent
> 
>    Refactor NumPy based data wrapper
> 
>    Add "utils"
> 
>    Adapt the sched_wakeup.py example script to use the new tracecruncher
> 
>      module
> 
> 
> 
>   examples/sched_wakeup.py  |  30 ++---
> 
>   setup.py                  |  61 +++++++++
> 
>   src/common.h              |  20 +++
> 
>   src/datawrapper.pyx       | 201 ++++++++++++++++++++++++++++
> 
>   src/ftracepy.c            | 234 +++++++++++++++++++++++++++++++++
> 
>   src/ksharkpy.c            | 268 ++++++++++++++++++++++++++++++++++++++
> 
>   src/trace2matrix.c        |  29 +++++
> 
>   tracecruncher/__init__.py |   0
> 
>   tracecruncher/utils.py    |  54 ++++++++
> 
>   9 files changed, 882 insertions(+), 15 deletions(-)
> 
>   create mode 100644 setup.py
> 
>   create mode 100644 src/common.h
> 
>   create mode 100644 src/datawrapper.pyx
> 
>   create mode 100644 src/ftracepy.c
> 
>   create mode 100644 src/ksharkpy.c
> 
>   create mode 100644 src/trace2matrix.c
> 
>   create mode 100644 tracecruncher/__init__.py
> 
>   create mode 100644 tracecruncher/utils.py
> 
> 
> 
> --
> 
> 2.20.1
> 
> 
> 
> IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-01-07 16:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-12  9:02 [PATCH 0/5] Build trace-cruncher as Python pakage Yordan Karadzhov (VMware)
2019-12-12  9:02 ` [PATCH 1/5] Refactor the part of the interface that relies on libkshark Yordan Karadzhov (VMware)
2019-12-12  9:02 ` [PATCH 2/5] Refactor the part of the interface that relies on libtraceevent Yordan Karadzhov (VMware)
2019-12-12  9:02 ` [PATCH 3/5] Refactor NumPy based data wrapper Yordan Karadzhov (VMware)
2019-12-12  9:02 ` [PATCH 4/5] Add "utils" Yordan Karadzhov (VMware)
2019-12-12  9:02 ` [PATCH 5/5] Adapt the sched_wakeup.py example script to use the new tracecruncher module Yordan Karadzhov (VMware)
2019-12-31 18:37 ` [PATCH 0/5] Build trace-cruncher as Python pakage Douglas Raillard
2020-01-07 16:59   ` 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).