[PATCH 5/5] kernel-shark: Optimize the logic of the filtering menus

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The logic of the menus is optimized to automatically decide whether is
more efficient to use positive (show only) or negative (do not show)
ID filter. Note that there is no difference between using positive or
negative filters in terms of performance, because the IDs of each filter
are stored in a hash table, hence the checks are made in constant time.
The motivation is just to keep the configuration of the filters as
simple as possible, in particular when we want this configuration to be
saved and later restored from the Session. The patch also fixes the
problem of negative filters set from the Quick Context menu not being
shown in the main filtering menus.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx>
---
 kernel-shark/src/KsMainWindow.cpp | 184 +++++++++++++++++++++++-------
 kernel-shark/src/KsMainWindow.hpp |  12 ++
 2 files changed, 156 insertions(+), 40 deletions(-)

diff --git a/kernel-shark/src/KsMainWindow.cpp b/kernel-shark/src/KsMainWindow.cpp
index 9b5fc2d..aed28a8 100644
--- a/kernel-shark/src/KsMainWindow.cpp
+++ b/kernel-shark/src/KsMainWindow.cpp
@@ -594,114 +594,218 @@ void KsMainWindow::_graphFilterSync(int state)
 	_data.update();
 }
 
+QVector<bool> KsMainWindow::_getFilterCbStatus(tracecmd_filter_id *showFilter,
+					       tracecmd_filter_id *hideFilter,
+					       QVector<int> ids)
+{
+	QVector<bool> v;
+
+	if (!kshark_this_filter_is_set(showFilter) &&
+	    !kshark_this_filter_is_set(hideFilter)) {
+		return v;
+	} else {
+		int n = ids.count();
+		bool show, hide;
+
+		if (kshark_this_filter_is_set(showFilter)) {
+			/*
+			 * The "show only" filter is set. The default status
+			 * of all CheckBoxes will be "unchecked".
+			 */
+			v = QVector<bool>(n, false);
+			for (int i = 0; i < n; ++i) {
+				show = !!tracecmd_filter_id_find(showFilter,
+								 ids[i]);
+
+				hide = !!tracecmd_filter_id_find(hideFilter,
+								 ids[i]);
+
+				if (show && !hide) {
+					/*
+					 * Both "show" and "hide" define this
+					 * Id as visible. Set the status of
+					 * its CheckBoxes to "checked".
+					 */
+					v[i] = true;
+				}
+			}
+		} else { // Only hide filter is set.
+			v = QVector<bool>(n, true);
+			for (int i = 0; i < n; ++i) {
+				hide = !!tracecmd_filter_id_find(hideFilter,
+								 ids[i]);
+
+				if (hide)
+					v[i] = false;
+			}
+		}
+	}
+
+	return v;
+}
+
+QVector<int> KsMainWindow::_revertFilterIds(QVector<int> all, QVector<int> vec)
+{
+	QVector<int> diff;
+
+	/*
+	 * The Ids may not be sorted, becausein in the widgets the items are
+	 * shown sorted by name. Get those Ids sorted first.
+	 */
+	std::sort(vec.begin(), vec.end());
+
+	/*
+	 * The IDs of the "do not show" filter are given by the difference
+	 * between "all Ids" and the "show only" filter.
+	 */
+	std::set_difference(all.begin(), all.end(),
+			    vec.begin(), vec.end(),
+			    std::inserter(diff, diff.begin()));
+
+	return diff;
+}
+
 void KsMainWindow::_showEvents()
 {
 	kshark_context *kshark_ctx(nullptr);
 	KsCheckBoxWidget *events_cb;
 	KsCheckBoxDialog *dialog;
+	QVector<bool> v;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
 	events_cb = new KsEventsCheckBoxWidget(_data.tep(), this);
 	dialog = new KsCheckBoxDialog(events_cb, this);
+	v = _getFilterCbStatus(kshark_ctx->show_event_filter,
+			       kshark_ctx->hide_event_filter,
+			       KsUtils::getEventIdList(TEP_EVENT_SORT_SYSTEM));
 
-	if (!kshark_ctx->show_event_filter ||
-	    !kshark_ctx->show_event_filter->count) {
+	if (v.count() == 0) {
 		events_cb->setDefault(true);
 	} else {
 		/*
-		 * The event filter contains IDs. Make this visible in the
-		 * CheckBox Widget.
+		 * Some of the event filters contains IDs. Make this visible
+		 * in the CheckBox Widget.
 		 */
-		tep_event **events =
-			tep_list_events(_data.tep(), TEP_EVENT_SORT_SYSTEM);
-		int nEvts = tep_get_events_count(_data.tep());
-		QVector<bool> v(nEvts, false);
-
-		for (int i = 0; i < nEvts; ++i) {
-			if (tracecmd_filter_id_find(kshark_ctx->show_event_filter,
-						    events[i]->id))
-				v[i] = true;
-		}
-
 		events_cb->set(v);
 	}
 
 	connect(dialog,		&KsCheckBoxDialog::apply,
-		&_data,		&KsDataStore::applyPosEventFilter);
+		this,		&KsMainWindow::_applyEventFilter);
 
 	dialog->show();
 }
 
+void KsMainWindow::_applyEventFilter(QVector<int> showEvents)
+{
+	QVector<int> allEvents = KsUtils::getEventIdList();
+
+	if (showEvents.count() < allEvents.count() / 2) {
+		_data.applyPosEventFilter(showEvents);
+	} else {
+		/*
+		 * It is more efficiant to apply negative (do not show) filter.
+		 */
+		QVector<int> diff = _revertFilterIds(allEvents, showEvents);
+		_data.applyNegEventFilter(diff);
+	}
+}
+
 void KsMainWindow::_showTasks()
 {
 	kshark_context *kshark_ctx(nullptr);
 	KsCheckBoxWidget *tasks_cbd;
 	KsCheckBoxDialog *dialog;
+	QVector<bool> v;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
 	tasks_cbd = new KsTasksCheckBoxWidget(_data.tep(), true, this);
 	dialog = new KsCheckBoxDialog(tasks_cbd, this);
+	v = _getFilterCbStatus(kshark_ctx->show_task_filter,
+			       kshark_ctx->hide_task_filter,
+			       KsUtils::getPidList());
 
-	if (!kshark_ctx->show_task_filter ||
-	    !kshark_ctx->show_task_filter->count) {
+	if (v.count() == 0) {
 		tasks_cbd->setDefault(true);
 	} else {
-		QVector<int> pids = KsUtils::getPidList();
-		int nPids = pids.count();
-		QVector<bool> v(nPids, false);
-
-		for (int i = 0; i < nPids; ++i) {
-			if (tracecmd_filter_id_find(kshark_ctx->show_task_filter,
-						    pids[i]))
-				v[i] = true;
-		}
-
+		/*
+		 * Some of the task filters contains PIDs. Make this visible
+		 * in the CheckBox Widget.
+		 */
 		tasks_cbd->set(v);
 	}
 
 	connect(dialog,		&KsCheckBoxDialog::apply,
-		&_data,		&KsDataStore::applyPosTaskFilter);
+		this,		&KsMainWindow::_applyTaskFilter);
 
 	dialog->show();
 }
 
+void KsMainWindow::_applyTaskFilter(QVector<int> showPids)
+{
+	QVector<int> allPids = KsUtils::getPidList();
+
+	if (showPids.count() <  allPids.count() / 2) {
+		_data.applyPosTaskFilter(showPids);
+	} else {
+		/*
+		 * It is more efficiant to apply negative (do not show) filter.
+		 */
+		QVector<int> diff = _revertFilterIds(allPids, showPids);
+		_data.applyNegTaskFilter(diff);
+	}
+}
+
 void KsMainWindow::_showCPUs()
 {
 	kshark_context *kshark_ctx(nullptr);
 	KsCheckBoxWidget *cpu_cbd;
 	KsCheckBoxDialog *dialog;
+	QVector<bool> v;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
 	cpu_cbd = new KsCPUCheckBoxWidget(_data.tep(), this);
 	dialog = new KsCheckBoxDialog(cpu_cbd, this);
+	v = _getFilterCbStatus(kshark_ctx->show_cpu_filter,
+			       kshark_ctx->hide_cpu_filter,
+			       KsUtils::getCPUList());
 
-	if (!kshark_ctx->show_cpu_filter ||
-	    !kshark_ctx->show_cpu_filter->count) {
+	if (v.count() == 0) {
 		cpu_cbd->setDefault(true);
 	} else {
-		int nCPUs = tep_get_cpus(_data.tep());
-		QVector<bool> v(nCPUs, false);
-
-		for (int i = 0; i < nCPUs; ++i) {
-			if (tracecmd_filter_id_find(kshark_ctx->show_cpu_filter, i))
-				v[i] = true;
-		}
-
+		/*
+		 * Some of the CPU filters contains IDs. Make this visible
+		 * in the CheckBox Widget.
+		 */
 		cpu_cbd->set(v);
 	}
 
 	connect(dialog,		&KsCheckBoxDialog::apply,
-		&_data,		&KsDataStore::applyPosCPUFilter);
+		this,		&KsMainWindow::_applyCPUFilter);
 
 	dialog->show();
 }
 
+void KsMainWindow::_applyCPUFilter(QVector<int> showCPUs)
+{
+	QVector<int> allCPUs = KsUtils::getCPUList();
+
+	if (showCPUs.count() < allCPUs.count() / 2) {
+		_data.applyPosCPUFilter(showCPUs);
+	} else {
+		/*
+		 * It is more efficiant to apply negative (do not show) filter.
+		 */
+		QVector<int> diff = _revertFilterIds(allCPUs, showCPUs);
+		_data.applyNegCPUFilter(diff);
+	}
+}
+
 void KsMainWindow::_advancedFiltering()
 {
 	KsAdvFilteringDialog *dialog;
diff --git a/kernel-shark/src/KsMainWindow.hpp b/kernel-shark/src/KsMainWindow.hpp
index 59030e4..ecfc12c 100644
--- a/kernel-shark/src/KsMainWindow.hpp
+++ b/kernel-shark/src/KsMainWindow.hpp
@@ -177,6 +177,18 @@ private:
 
 	void _graphFilterSync(int state);
 
+	QVector<bool> _getFilterCbStatus(tracecmd_filter_id *showFilter,
+					 tracecmd_filter_id *hideFilter,
+					 QVector<int> ids);
+
+	QVector<int> _revertFilterIds(QVector<int> all, QVector<int> vec);
+
+	void _applyEventFilter(QVector<int> showEvents);
+
+	void _applyTaskFilter(QVector<int> showPids);
+
+	void _applyCPUFilter(QVector<int> showCPUs);
+
 	void _showEvents();
 
 	void _showTasks();
-- 
2.20.1




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux