diff mbox series

[24/24] kernel-shark: Show Task plots from command lime

Message ID 20210201172358.175407-25-y.karadz@gmail.com (mailing list archive)
State Superseded
Headers show
Series Complete the KernelShark v2 transformation | expand

Commit Message

Yordan Karadzhov Feb. 1, 2021, 5:23 p.m. UTC
We add a new command line option for starting KernelShark that allows
the user to select Task plots to be shown. The new option is similar
to "--pid" but the tasks can be specified by name.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 src/KsUtils.cpp               | 32 ++++++++++++++++++++++++++++++++
 src/KsUtils.hpp               |  2 ++
 src/kernelshark.cpp           | 17 +++++++++++++----
 tests/libkshark-gui-tests.cpp | 25 +++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/src/KsUtils.cpp b/src/KsUtils.cpp
index 27cda55..ec53267 100644
--- a/src/KsUtils.cpp
+++ b/src/KsUtils.cpp
@@ -548,6 +548,38 @@  QVector<int> parseIdList(QString v_str)
 	return v;
 }
 
+/**
+ * @brief Convert a string containing task names into a list of PID numbers.
+ */
+QMap<int, QVector<int>> parseTaskList(QString v_str)
+{
+	QStringList taskList = v_str.split(",", QString::SkipEmptyParts);
+	QVector<int> streamIds, allPids;
+	kshark_context *kshark_ctx(nullptr);
+	QMap<int, QVector<int>> ret;
+	QString name;
+
+	if (!kshark_instance(&kshark_ctx))
+		return {};
+
+	streamIds = getStreamIdList(kshark_ctx);
+	for (auto const sd: streamIds) {
+		allPids = getPidList(sd);
+		for (auto const pid: allPids) {
+			name = kshark_comm_from_pid(sd, pid);
+			if (name.isEmpty())
+				continue;
+
+			for (auto const task: taskList) {
+				if(name == task)
+					ret[sd].append(pid);
+			}
+		}
+	}
+
+	return ret;
+}
+
 /**
  * @brief Split the ststem name from the actual name of the event itself.
  *
diff --git a/src/KsUtils.hpp b/src/KsUtils.hpp
index 0d2c9c3..cf209bc 100644
--- a/src/KsUtils.hpp
+++ b/src/KsUtils.hpp
@@ -161,6 +161,8 @@  QStringList splitArguments(QString cmd);
 
 QVector<int> parseIdList(QString v_str);
 
+QMap<int, QVector<int>> parseTaskList(QString v_str);
+
 QStringList getTepEvtName(int sd, int eventId);
 
 /** Get a string to be used as a standard name of a CPU graph. */
diff --git a/src/kernelshark.cpp b/src/kernelshark.cpp
index 41ffbe7..8ed4948 100644
--- a/src/kernelshark.cpp
+++ b/src/kernelshark.cpp
@@ -32,7 +32,8 @@  void usage(const char *prog)
 	printf("  -s	import a session\n");
 	printf("  -l	import the last session\n");
 	puts(" --cpu	show plots for CPU cores, default is \"show all\"");
-	puts(" --pid	show plots for tasks, default is \"do not show\"");
+	puts(" --pid	show plots for tasks (by PID), default is \"do not show\"");
+	puts(" --task	show plots for tasks (by name), default is \"do not show\"");
 	puts("\n example:");
 	puts("  kernelshark -i mytrace.dat --cpu 1,4-7 --pid 11 -p path/to/my/plugin/myplugin.so\n");
 }
@@ -42,6 +43,7 @@  static option longOptions[] = {
 	{"help", no_argument, nullptr, 'h'},
 	{"pid", required_argument, nullptr, KS_LONG_OPTS},
 	{"cpu", required_argument, nullptr, KS_LONG_OPTS},
+	{"task", required_argument, nullptr, KS_LONG_OPTS},
 	{nullptr, 0, nullptr, 0}
 };
 
@@ -50,6 +52,7 @@  int main(int argc, char **argv)
 	QVector<int> cpuPlots, taskPlots;
 	bool fromSession = false;
 	int optionIndex = 0;
+	QString taskList;
 	int c;
 
 	QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@@ -67,7 +70,8 @@  int main(int argc, char **argv)
 				cpuPlots.append(KsUtils::parseIdList(QString(optarg)));
 			else if (strcmp(longOptions[optionIndex].name, "pid") == 0)
 				taskPlots.append(KsUtils::parseIdList(QString(optarg)));
-
+			else if (strcmp(longOptions[optionIndex].name, "task") == 0)
+				taskList = QString(optarg);
 			break;
 
 		case 'h':
@@ -136,9 +140,14 @@  int main(int argc, char **argv)
 		return ids;
 	};
 
-	if (cpuPlots.count() || taskPlots.count()) {
+	if (cpuPlots.count() || taskPlots.count() || taskList.size()) {
 		ks.setCPUPlots(0, lamOrderIds(cpuPlots));
-		ks.setTaskPlots(0, lamOrderIds(taskPlots));
+
+		auto pidMap = KsUtils::parseTaskList(taskList);
+		pidMap[0].append(taskPlots);
+		for (auto it = pidMap.begin(); it != pidMap.end(); ++it) {
+			ks.setTaskPlots(it.key(), lamOrderIds(it.value()));
+		}
 	}
 
 	ks.raise();
diff --git a/tests/libkshark-gui-tests.cpp b/tests/libkshark-gui-tests.cpp
index 5a0ca01..bc49194 100644
--- a/tests/libkshark-gui-tests.cpp
+++ b/tests/libkshark-gui-tests.cpp
@@ -286,3 +286,28 @@  BOOST_AUTO_TEST_CASE(GraphModel)
 	model.reset();
 	BOOST_CHECK_EQUAL(model.rowCount({}), 0);
 }
+
+BOOST_AUTO_TEST_CASE(KsUtils_parseTasks)
+{
+	QVector<int> pids{28121, 28137, 28141, 28199, 28201, 205666, 267481};
+	kshark_context *kshark_ctx{nullptr};
+	kshark_entry **data{nullptr};
+	std::string file(KS_TEST_DIR);
+	ssize_t n_rows;
+	int sd;
+
+	kshark_instance(&kshark_ctx);
+	file += "/trace_test1.dat";
+	sd = kshark_open(kshark_ctx, file.c_str());
+	n_rows = kshark_load_entries(kshark_ctx, sd, &data);
+
+	auto pids_test = parseTaskList("zoom,sleep");
+	BOOST_CHECK(pids == pids_test[0]);
+
+	for (ssize_t r = 0; r < n_rows; ++r)
+		free(data[r]);
+	free(data);
+
+	kshark_close(kshark_ctx, sd);
+	kshark_free(kshark_ctx);
+}