[Xfce4-commits] [apps/xfce4-taskmanager] 01/01: Rework the way the model is updated (bug 14403)

noreply at xfce.org noreply at xfce.org
Sun May 27 11:37:22 CEST 2018


This is an automated email from the git hooks/post-receive script.

l   a   n   d   r   y       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository apps/xfce4-taskmanager.

commit fd149b63df44eeace3851ca40812d52684f4e2c6
Author: Rozhuk Ivan <rozhuk.im at gmail.com>
Date:   Sun May 27 11:35:00 2018 +0200

    Rework the way the model is updated (bug 14403)
    
    - Do more lazy updates
    - More robust to quick process creation/deletion
    - Use bsearch to look in the sorted list of processes.
    
    Should consume less resources..
---
 src/task-manager.c | 312 +++++++++++++++++++----------------------------------
 1 file changed, 111 insertions(+), 201 deletions(-)

diff --git a/src/task-manager.c b/src/task-manager.c
index f33f326..db7a692 100644
--- a/src/task-manager.c
+++ b/src/task-manager.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010 Mike Massonnet, <mmassonnet at xfce.org>
+ * Copyright (c) 2018 Rozhuk Ivan <rozhuk.im at gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -11,6 +12,7 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <pwd.h>
@@ -73,16 +75,14 @@ static void	xtm_task_manager_finalize			(GObject *object);
 static void	setting_changed					(GObject *object, GParamSpec *pspec, XtmTaskManager *manager);
 #ifdef HAVE_WNCK
 static void	model_add_task					(GtkTreeModel *model, Task *task, App *app, glong timestamp);
-static void	model_update_tree_iter				(GtkTreeModel *model, GtkTreeIter *iter, Task *task, App *app);
-static void	model_update_task				(GtkTreeModel *model, Task *task, App *app);
+static void	model_update_tree_iter				(GtkTreeModel *model, GtkTreeIter *iter, glong timestamp, gboolean update_cmd_line, Task *task, App *app);
 #else
 static void	model_add_task					(GtkTreeModel *model, Task *task, glong timestamp);
-static void	model_update_tree_iter				(GtkTreeModel *model, GtkTreeIter *iter, Task *task);
-static void	model_update_task				(GtkTreeModel *model, Task *task);
+static void	model_update_tree_iter				(GtkTreeModel *model, GtkTreeIter *iter, glong timestamp, gboolean update_cmd_line, Task *task);
 #endif
-static void	model_mark_tree_iter_as_removed			(GtkTreeModel *model, GtkTreeIter *iter);
+static void	model_mark_tree_iter_as_removed			(GtkTreeModel *model, GtkTreeIter *iter, glong timestamp);
 static void	model_remove_tree_iter				(GtkTreeModel *model, GtkTreeIter *iter);
-static void	model_find_tree_iter_for_pid			(GtkTreeModel *model, guint pid, GtkTreeIter *iter);
+static gboolean	task_list_find_for_pid				(GArray *task_list, guint pid, Task **task, guint *idx);
 static glong	__current_timestamp				(void);
 
 
@@ -169,20 +169,9 @@ model_add_task (GtkTreeModel *model, Task *task, glong timestamp)
 #endif
 {
 	GtkTreeIter iter;
-	gchar *cmdline;
-
-#ifdef HAVE_WNCK
-	if (app != NULL && full_cmdline == FALSE)
-		cmdline = g_strdup (app->name);
-	else
-		cmdline = pretty_cmdline (task->cmdline, task->name);
-#else
-	cmdline = pretty_cmdline (task->cmdline, task->name);
-#endif
 
 	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 	gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-		XTM_PTV_COLUMN_COMMAND, cmdline,
 		XTM_PTV_COLUMN_PID, task->pid,
 		XTM_PTV_COLUMN_STATE, task->state,
 		XTM_PTV_COLUMN_UID, task->uid,
@@ -192,23 +181,21 @@ model_add_task (GtkTreeModel *model, Task *task, glong timestamp)
 		XTM_PTV_COLUMN_TIMESTAMP, timestamp,
 		-1);
 #ifdef HAVE_WNCK
-	model_update_tree_iter (model, &iter, task, app);
+	model_update_tree_iter (model, &iter, timestamp, TRUE, task, app);
 #else
-	model_update_tree_iter (model, &iter, task);
+	model_update_tree_iter (model, &iter, timestamp, TRUE, task);
 #endif
-
-	g_free (cmdline);
 }
 
 static void
-model_mark_tree_iter_as_removed (GtkTreeModel *model, GtkTreeIter *iter)
+model_mark_tree_iter_as_removed (GtkTreeModel *model, GtkTreeIter *iter, glong timestamp)
 {
 	gtk_list_store_set (GTK_LIST_STORE (model), iter,
 		XTM_PTV_COLUMN_CPU, 0.0,
 		XTM_PTV_COLUMN_CPU_STR, "-",
 		XTM_PTV_COLUMN_BACKGROUND, "#e57373",
 		XTM_PTV_COLUMN_FOREGROUND, "#000000",
-		XTM_PTV_COLUMN_TIMESTAMP, __current_timestamp (),
+		XTM_PTV_COLUMN_TIMESTAMP, timestamp,
 		-1);
 }
 
@@ -220,9 +207,9 @@ model_remove_tree_iter (GtkTreeModel *model, GtkTreeIter *iter)
 
 static void
 #ifdef HAVE_WNCK
-model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task, App *app)
+model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, glong timestamp, gboolean update_cmd_line, Task *task, App *app)
 #else
-model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task)
+model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, glong timestamp, gboolean update_cmd_line, Task *task)
 #endif
 {
 	gchar *vsz, *rss, cpu[16];
@@ -258,9 +245,9 @@ model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task)
 		gtk_list_store_set (GTK_LIST_STORE (model), iter, XTM_PTV_COLUMN_COMMAND, cmdline, -1);
 		g_free (cmdline);
 	}
-	else if (model_update_forced)
+	else if (update_cmd_line)
 #else
-	if (model_update_forced)
+	if (update_cmd_line)
 #endif
 	{
 		gchar *cmdline = pretty_cmdline (task->cmdline, task->name);
@@ -273,10 +260,10 @@ model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task)
 		/* Set yellow color for changing state */
 		background = g_strdup ("#fff176");
 		foreground = g_strdup ("#000000");
-		old_timestamp = __current_timestamp () - TIMESTAMP_DELTA + 3;
+		old_timestamp = timestamp - TIMESTAMP_DELTA + 3;
 	}
 
-	if (__current_timestamp () - old_timestamp <= TIMESTAMP_DELTA)
+	if (timestamp != 0 && (timestamp - old_timestamp) <= TIMESTAMP_DELTA)
 	{
 		/* Set green color for started task */
 		background = (background == NULL) ? g_strdup ("#aed581") : background;
@@ -311,36 +298,29 @@ model_update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task)
 	g_free (rss);
 }
 
-static void
-#ifdef HAVE_WNCK
-model_update_task (GtkTreeModel *model, Task *task, App *app)
-#else
-model_update_task (GtkTreeModel *model, Task *task)
-#endif
+static gboolean
+task_list_find_for_pid (GArray *task_list, guint pid, Task **task, guint *idx)
 {
-	GtkTreeIter iter;
-	model_find_tree_iter_for_pid (model, task->pid, &iter);
-#ifdef HAVE_WNCK
-	model_update_tree_iter (model, &iter, task, app);
-#else
-	model_update_tree_iter (model, &iter, task);
-#endif
-}
+	Task *task_tmp, tkey;
+	tkey.pid = pid;
+	task_tmp = bsearch(&tkey, task_list->data, task_list->len, sizeof(Task), task_pid_compare_fn);
 
-static void
-model_find_tree_iter_for_pid (GtkTreeModel *model, guint pid, GtkTreeIter *iter)
-{
-	gboolean valid;
-	guint pid_iter;
-
-	valid = gtk_tree_model_get_iter_first (model, iter);
-	while (valid)
+	if (NULL != task)
 	{
-		gtk_tree_model_get (model, iter, XTM_PTV_COLUMN_PID, &pid_iter, -1);
-		if (pid == pid_iter)
-			break;
-		valid = gtk_tree_model_iter_next (model, iter);
+		(*task) = task_tmp;
 	}
+	if (NULL != idx)
+	{
+		if (NULL != task_tmp)
+		{
+			(*idx) = (((size_t)task_tmp - (size_t)task_list->data) / sizeof(Task));
+		}
+		else
+		{
+			(*idx) = (~((guint)0));
+		}
+	}
+	return ((NULL != task_tmp));
 }
 
 static glong
@@ -419,187 +399,117 @@ xtm_task_manager_get_task_list (XtmTaskManager *manager)
 void
 xtm_task_manager_update_model (XtmTaskManager *manager)
 {
-	static GArray *removed_tasks = NULL;
 	GArray *array;
 	guint i;
+	GtkTreeIter iter;
+	gboolean valid;
+	glong timestamp;
+#ifdef HAVE_WNCK
+	App *app;
+#endif
 
 	g_return_if_fail (XTM_IS_TASK_MANAGER (manager));
 
-	if (removed_tasks == NULL)
-		removed_tasks = g_array_new (FALSE, FALSE, sizeof (GtkTreeIter));
-
-	/* Retrieve initial task list and return */
-	if (manager->tasks->len == 0)
-	{
-		get_task_list (manager->tasks);
-		for (i = 0; i < manager->tasks->len; i++)
-		{
-			Task *task = &g_array_index (manager->tasks, Task, i);
-#ifdef HAVE_WNCK
-			App *app = xtm_app_manager_get_app_from_pid (manager->app_manager, task->pid);
-			model_add_task (manager->model, task, app, 0);
-#else
-			model_add_task (manager->model, task, 0);
-#endif
-#if DEBUG
-			g_print ("%5d %5s %15s %.50s\n", task->pid, task->uid_name, task->name, task->cmdline);
-#endif
-		}
-		return;
-	}
+	/* First time fast refresh. */
+	timestamp = ((manager->tasks->len == 0) ? 0 : __current_timestamp ());
 
 	/* Retrieve new task list */
 	array = g_array_new (FALSE, FALSE, sizeof (Task));
 	get_task_list (array);
 
-	/* Remove terminated tasks */
-	for (i = 0; i < removed_tasks->len; i++)
+	/* Remove terminated tasks, mark to remove, update existing. */
+	valid = gtk_tree_model_get_iter_first (manager->model, &iter);
+	while (valid)
 	{
-		GtkTreeIter *iter = &g_array_index (removed_tasks, GtkTreeIter, i);
+		gint pid;
+		gchar *cpu_str;
 		glong old_timestamp;
-		gtk_tree_model_get (manager->model, iter, XTM_PTV_COLUMN_TIMESTAMP, &old_timestamp, -1);
-		if (__current_timestamp () - old_timestamp > TIMESTAMP_DELTA)
+		gboolean found;
+		Task *task, *task_new;
+		GtkTreeIter cur_iter = iter;
+
+		gtk_tree_model_get (manager->model, &iter, XTM_PTV_COLUMN_CPU_STR, &cpu_str, XTM_PTV_COLUMN_TIMESTAMP, &old_timestamp, XTM_PTV_COLUMN_PID, &pid, -1);
+		found = (g_strcmp0 (cpu_str, "-") == 0);
+		g_free (cpu_str);
+		valid = gtk_tree_model_iter_next (manager->model, &iter);
+		if (found && (timestamp - old_timestamp) > TIMESTAMP_DELTA)
 		{
-#if DEBUG
-			gint pid;
-			gtk_tree_model_get (manager->model, iter, XTM_PTV_COLUMN_PID, &pid, -1);
-			g_debug ("Remove old task %d", pid);
-#endif
-			model_remove_tree_iter (manager->model, iter);
-			g_array_remove_index (removed_tasks, i);
+			G_DEBUG_FMT ("Remove old task %d", pid);
+			model_remove_tree_iter (manager->model, &cur_iter);
+			continue;
 		}
-	}
 
-	for (i = 0; i < manager->tasks->len; i++)
-	{
-		guint j;
-		Task *tasktmp;
-		Task *task = &g_array_index (manager->tasks, Task, i);
-		gboolean found = FALSE;
-
-		for (j = 0; j < array->len; j++)
+		/* Looking for new terminated tasks and check updates for existing. */
+		found = task_list_find_for_pid (manager->tasks, pid, &task, &i);
+		if (FALSE == found)
 		{
-			tasktmp = &g_array_index (array, Task, j);
-			if (task->pid != tasktmp->pid)
-				continue;
-			found = TRUE;
-			break;
+			G_DEBUG_FMT ("Cached task not found for pid: %d", pid);
+			continue;
 		}
-
-		if (found == FALSE)
+		found = task_list_find_for_pid (array, pid, &task_new, NULL);
+		if (FALSE == found) /* Mark as removed. */
 		{
-			GtkTreeIter iter;
-#if DEBUG
-			g_debug ("Task %d '%s' terminated, marking as removed", task->pid, task->name);
-#endif
-			model_find_tree_iter_for_pid (manager->model, task->pid, &iter);
-			model_mark_tree_iter_as_removed (manager->model, &iter);
-			g_array_append_val (removed_tasks, iter);
+			G_DEBUG_FMT ("Task %d '%s' terminated, marking as removed", pid, task->name);
+			model_mark_tree_iter_as_removed (manager->model, &cur_iter, timestamp);
 			g_array_remove_index (manager->tasks, i);
+			continue;
 		}
-	}
-
-	/* Append started tasks and update existing ones */
-	for (i = 0; i < array->len; i++)
-	{
-		guint j;
-		Task *tasktmp = &g_array_index (array, Task, i);
-		gboolean found = FALSE;
 
-		for (j = 0; j < manager->tasks->len; j++)
-		{
-			Task *task = &g_array_index (manager->tasks, Task, j);
+		/* Task alive, check for update. */
 #ifdef HAVE_WNCK
-			App *app;
+		app = xtm_app_manager_get_app_from_pid (manager->app_manager, pid);
 #endif
-			gboolean updated = FALSE;
-
-			if (task->pid != tasktmp->pid)
-				continue;
-
-#ifdef HAVE_WNCK
-			app = xtm_app_manager_get_app_from_pid (manager->app_manager, task->pid);
-#endif
-			found = TRUE;
-
-			/* Update the model (with the rest) only if needed, this keeps the CPU cool */
-			if (model_update_forced
-				|| task->ppid != tasktmp->ppid
-				|| g_strcmp0 (task->state, tasktmp->state)
-				|| task->cpu_user != tasktmp->cpu_user
-				|| task->cpu_system != tasktmp->cpu_system
-				|| task->rss != tasktmp->rss
-				|| task->vsz != tasktmp->vsz
-				|| task->prio != tasktmp->prio)
-			{
-				updated = TRUE;
-				task->ppid = tasktmp->ppid;
-				g_strlcpy (task->state, tasktmp->state, sizeof (task->state));
-				task->cpu_user = tasktmp->cpu_user;
-				task->cpu_system = tasktmp->cpu_system;
-				task->rss = tasktmp->rss;
-				task->vsz = tasktmp->vsz;
-				task->prio = tasktmp->prio;
-#ifdef HAVE_WNCK
-				model_update_task (manager->model, tasktmp, app);
-#else
-				model_update_task (manager->model, tasktmp);
-#endif
-			}
+		gboolean need_update = FALSE;
+		gboolean update_cmd_line = FALSE;
 
+		/* Update the model (with the rest) only if needed, this keeps the CPU cool */
+		if (model_update_forced || 0 != memcmp(task, task_new, sizeof(Task)))
+		{
+			need_update = TRUE;
 			/* Update command name if needed (can happen) */
-			if (!model_update_forced && g_strcmp0 (task->cmdline, tasktmp->cmdline))
-			{
-				GtkTreeIter iter;
-				gchar *cmdline;
-
-				cmdline = pretty_cmdline (tasktmp->cmdline, tasktmp->name);
-				model_find_tree_iter_for_pid (manager->model, task->pid, &iter);
-				gtk_list_store_set (GTK_LIST_STORE (manager->model), &iter, XTM_PTV_COLUMN_COMMAND, cmdline, -1);
-				g_free (cmdline);
-			}
+			update_cmd_line = (model_update_forced || g_strcmp0 (task->cmdline, task_new->cmdline));
+			memcpy(task, task_new, sizeof(Task));
+		}
+		else /* Update color if needed */
+		{
+			gchar *color;
 
-			/* Update color if needed */
-			if (updated == FALSE)
+			gtk_tree_model_get (manager->model, &cur_iter, XTM_PTV_COLUMN_BACKGROUND, &color, -1);
+			if (color != NULL && (timestamp - old_timestamp) > TIMESTAMP_DELTA)
 			{
-				GtkTreeIter iter;
-				gchar *color;
-				glong old_timestamp;
-
-				model_find_tree_iter_for_pid (manager->model, task->pid, &iter);
-				gtk_tree_model_get (manager->model, &iter, XTM_PTV_COLUMN_BACKGROUND, &color, XTM_PTV_COLUMN_TIMESTAMP, &old_timestamp, -1);
-
-				if (color != NULL && __current_timestamp () - old_timestamp > TIMESTAMP_DELTA)
-				{
-#if DEBUG
-					g_debug ("Remove color from running PID %d", task->pid);
-#endif
+				need_update = TRUE;
+				G_DEBUG_FMT ("Remove color from running PID %d", pid);
+			}
+			g_free (color);
+		}
+		
+		if (need_update)
+		{
 #ifdef HAVE_WNCK
-					model_update_task (manager->model, tasktmp, app);
+			model_update_tree_iter (manager->model, &cur_iter, timestamp, update_cmd_line, task_new, app);
 #else
-					model_update_task (manager->model, tasktmp);
+			model_update_tree_iter (manager->model, &cur_iter, timestamp, update_cmd_line, task_new);
 #endif
-				}
-
-				g_free (color);
-			}
-
-			break;
 		}
+	}
 
-		if (found == FALSE)
-		{
+	/* Append started tasks and update existing ones */
+	for (i = 0; i < array->len; i++)
+	{
+		Task *tasktmp = &g_array_index (array, Task, i);
+
+		if (task_list_find_for_pid (manager->tasks, tasktmp->pid, NULL, NULL))
+			continue;
 #ifdef HAVE_WNCK
-			App *app = xtm_app_manager_get_app_from_pid (manager->app_manager, tasktmp->pid);
-			model_add_task (manager->model, tasktmp, app, __current_timestamp ());
+		app = xtm_app_manager_get_app_from_pid (manager->app_manager, tasktmp->pid);
+		model_add_task (manager->model, tasktmp, app, timestamp);
 #else
-			model_add_task (manager->model, tasktmp, __current_timestamp ());
+		model_add_task (manager->model, tasktmp, timestamp);
 #endif
-			g_array_append_val (manager->tasks, *tasktmp);
-#if DEBUG
-			g_debug ("Add new task %d %s", tasktmp->pid, tasktmp->name);
-#endif
-		}
+		/* XXX: add bininsert() here. */
+		g_array_append_val (manager->tasks, *tasktmp);
+		g_array_sort (manager->tasks, task_pid_compare_fn);
+		G_DEBUG_FMT ("Add new task %d %s", tasktmp->pid, tasktmp->name);
 	}
 
 	g_array_free (array, TRUE);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list