improve ps performance

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

 



Hello dave,

Due to the task_to_pid() function is exported in defs.h and affects extension module, I just fix the third part which repeated get the value of filepages and spend much time to get the value of rss at the get_task_mem_usage() function.

Please check this patch to see detailed information.

Thanks,
  Pan
>From cd77fce663c5a796c97513c62045a2cc22c0264e Mon Sep 17 00:00:00 2001
From: panfengyun <panfy.fnst@xxxxxxxxxxxxxx>
Date: Wed, 20 Aug 2014 16:38:10 +0800
Subject: [PATCH] improve ps performance

When a core file contains numerous tasks, especilly on RHEL 7, it will spend too
much time when using ps command to display tasks. At the get_task_mem_usage() 
function, repeated get the value of filepages and spend much time to get the value 
of rss at FOR statement.

Please check the patch to see detailed information.

I test the patch on two OS, and the result is like below(using the following two
command to create processes):
       1. on RHEL 6, using "./test2.sh 10 10000" to create 100k processes, the
          original ps command spends 179.9s, after applying my patch, the time is
          reduced to 72.41s.
       2. on RHEL 7, using "./test2.sh 100 1000" to create 100k processes, the
          original ps command spends 51873.6s, after applying my patch, the time is
          reduced to 41.89s.

test2.sh:
<cut>
a=$1
while [ $a -ge 0  ]
do
    sh /root/test.sh $2 &
    a=$((a-1))
done
sleep 10000
<cut>

test.sh:
<cut>
a=$1
if [[ $a -eq 0  ]]
then
    echo exit
    exit
fi
a=$((a-1))
sh /root/test.sh $a
sleep 10000
<cut>
---
 crash-7.0.7/defs.h   |   12 ++++
 crash-7.0.7/memory.c |   38 ++++++++----
 crash-7.0.7/task.c   |  159 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 197 insertions(+), 12 deletions(-)

diff --git a/crash-7.0.7/defs.h b/crash-7.0.7/defs.h
index 44df6ae..86e5211 100755
--- a/crash-7.0.7/defs.h
+++ b/crash-7.0.7/defs.h
@@ -758,13 +758,23 @@ struct task_context {                     /* context stored for each task */
 	int processor;
 	ulong ptask;
 	ulong mm_struct;
+	ulong tgid;
+	ulong tgid_task_context_index;
 	struct task_context *tc_next;
 };
 
+struct tgid_task_context{               /* context and tgid stored for each task */
+        ulong tgid;
+        struct task_context *tc;
+};
+
 struct task_table {                      /* kernel/local task table data */
 	struct task_context *current;
 	struct task_context *context_array;
+	struct tgid_task_context *ttc_array;
 	void (*refresh_task_table)(void);
+	long filepages;
+	long anonpages;
 	ulong flags;
         ulong task_start;
 	ulong task_end;
@@ -4788,6 +4798,8 @@ ulong pid_to_task(ulong);
 ulong task_to_pid(ulong);
 int task_exists(ulong);
 int is_kernel_thread(ulong);
+void set_ttc_array(void);
+void set_pages(void);
 int is_idle_thread(ulong);
 void get_idle_threads(ulong *, int);
 char *task_state_string(ulong, char *, int);
diff --git a/crash-7.0.7/memory.c b/crash-7.0.7/memory.c
index c97dd39..f9dc5f4 100755
--- a/crash-7.0.7/memory.c
+++ b/crash-7.0.7/memory.c
@@ -4108,11 +4108,8 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
 		if (VALID_MEMBER(mm_struct_rss_stat)) {
 			long anonpages, filepages;
 
-			if (!enumerator_value("MM_FILEPAGES", &filepages) ||
-			    !enumerator_value("MM_ANONPAGES", &anonpages)) {
-				filepages = 0;
-				anonpages = 1;
-			}
+			anonpages = tt->anonpages;
+			filepages = tt->filepages;
 			rss += LONG(tt->mm_struct +
 				OFFSET(mm_struct_rss_stat) +
 				OFFSET(mm_rss_stat_count) +
@@ -4125,16 +4122,30 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
 
 		/* Check whether SPLIT_RSS_COUNTING is enabled */
 		if (VALID_MEMBER(task_struct_rss_stat)) {
-			int i, sync_rss;
+			int sync_rss;
 			ulong tgid;
 			struct task_context *tc1;
+			struct tgid_task_context *ttc_array, *ttc, *start, *end;
 
-			tgid = task_tgid(task);
-
-			tc1 = FIRST_CONTEXT();
-			for (i = 0; i < RUNNING_TASKS(); i++, tc1++) {
-				if (task_tgid(tc1->task) != tgid)
-					continue;
+			ttc_array = tt->ttc_array;
+			tgid = tc->tgid;
+			ttc = ttc_array + tc->tgid_task_context_index;
+			start = ttc;
+			if (tc->tgid_task_context_index > 0)
+			{
+				while ((start > ttc_array) && ((start -1 )->tgid == start->tgid)) 
+					start--;
+			}
+			end = ttc;
+			if (tc->tgid_task_context_index < RUNNING_TASKS())
+                        {
+				while ((end < (ttc_array + (RUNNING_TASKS() - 1))) && 
+					(end->tgid == (end + 1)->tgid))
+					end++;
+			}
+			for (;start <= end;)
+			{
+				tc1 = start->tc;
 
 				/* count 0 -> filepages */
 				if (!readmem(tc1->task +
@@ -4160,6 +4171,9 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
 						continue;
 
 				rss += sync_rss;
+				if(start == (ttc_array + (RUNNING_TASKS() - 1)))
+					break;
+				start++;
 			}
 		}
 
diff --git a/crash-7.0.7/task.c b/crash-7.0.7/task.c
index 75b1964..d304cd6 100755
--- a/crash-7.0.7/task.c
+++ b/crash-7.0.7/task.c
@@ -493,6 +493,8 @@ task_init(void)
 	}
 
 	sort_context_array();
+	set_ttc_array();
+	set_pages();
 
 	if (pc->flags & SILENT)
 		initialize_task_state();
@@ -2281,6 +2283,7 @@ store_context(struct task_context *tc, ulong task, char *tp)
         int *processor_addr;
         ulong *parent_addr;
         ulong *mm_addr;
+	ulong *tgid;
         int has_cpu;
 	int do_verify;
 
@@ -2320,6 +2323,7 @@ store_context(struct task_context *tc, ulong task, char *tp)
 	else
         	parent_addr = (ulong *)(tp + OFFSET(task_struct_parent));
         mm_addr = (ulong *)(tp + OFFSET(task_struct_mm));
+	tgid = (ulong *)(tp + OFFSET(task_struct_tgid));
         has_cpu = task_has_cpu(task, tp);
 
         tc->pid = (ulong)(*pid_addr);
@@ -2327,6 +2331,7 @@ store_context(struct task_context *tc, ulong task, char *tp)
         tc->processor = *processor_addr;
         tc->ptask = *parent_addr;
         tc->mm_struct = *mm_addr;
+	tc->tgid = *tgid;
         tc->task = task;
         tc->tc_next = NULL;
 
@@ -3121,6 +3126,160 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
 	else
 		fprintf(fp, "%s\n", tc->comm);
 }
+/*
+ * adjust  heap, screening the index node.
+ */
+static void
+HeapAdjust(struct tgid_task_context *ttc, int index, int length)
+{
+	struct tgid_task_context *temp_ttc;
+	int child;
+
+	if (!(temp_ttc = (struct tgid_task_context *)GETBUF(sizeof(struct tgid_task_context))))
+	{
+		error(FATAL, "cannot malloc tgid_task_context temp_ttc");
+		return ;
+	}
+        temp_ttc->tc = NULL;
+
+	temp_ttc->tgid = (ttc + index)->tgid;
+	temp_ttc->tc = (ttc + index)->tc;
+	child = 2 * index + 1;
+	while (child < length)
+	{
+		if ((child < (length - 1)) && ((ttc + child)->tgid < (ttc + child + 1)->tgid))
+		{
+			++child;
+		}
+
+		if (temp_ttc->tgid < (ttc + child)->tgid)
+		{
+			(ttc + index)->tgid = (ttc + child)->tgid;
+			(ttc + index)->tc = (ttc + child)->tc;
+			index = child;
+			child = 2 * index + 1;
+		} else {
+			break;
+		}
+		(ttc + index)->tgid = temp_ttc->tgid;
+		(ttc + index)->tc = temp_ttc->tc;
+	}
+	FREEBUF(temp_ttc);
+}
+
+/*
+ *Initializing heap, then the smallext tgid number will be took in
+ *the first element;
+ */
+static void
+BuildingHeap(struct tgid_task_context *ttc, int length)
+{
+	int i;
+	for (i = (length - 1) / 2; i >= 0; --i)
+		HeapAdjust(ttc, i, length);
+}
+
+/*
+ * Heap sort algorithm
+ */
+static void
+HeapSort(struct tgid_task_context *ttc, int length)
+{
+	int i;
+	struct tgid_task_context *temp, *first, *last;
+
+	if (!(temp = (struct tgid_task_context *)GETBUF(sizeof(struct tgid_task_context))))
+	{
+		error(FATAL, "cannot malloc tgid_task_context temp");
+		return ;
+	}
+	temp->tc = NULL;
+
+	BuildingHeap(ttc, length);
+	for (i = length - 1; i > 0; --i)
+	{
+		first = ttc;
+		last = ttc + i;
+		temp->tgid = first->tgid;
+		temp->tc = first->tc;
+		first->tgid = last->tgid;
+		first->tc = last->tc;
+		last->tgid = temp->tgid;
+		last->tc = temp->tc;
+
+		HeapAdjust(ttc, 0 , i);		
+
+	}
+	FREEBUF(temp);
+}
+
+void 
+set_ttc_array(void)
+{
+	struct tgid_task_context *ttc;
+        struct task_context *tc;
+	int i;
+
+	if (VALID_MEMBER(mm_struct_rss))
+		return;
+	if (VALID_MEMBER(task_struct_rss_stat))
+	{
+		if (!(tt->ttc_array = (struct tgid_task_context *)
+			GETBUF(RUNNING_TASKS() * sizeof(struct tgid_task_context))))
+		{
+			error(FATAL, "cannot GETBU ttc array (%d tasks)",RUNNING_TASKS());
+			return ;
+		}
+		/*
+		 * init ttc
+ 		 */	
+		tc = FIRST_CONTEXT();
+		ttc = tt->ttc_array;
+		for (i = 0; i < RUNNING_TASKS(); i++, tc++, ttc++)
+		{
+			ttc->tgid = tc->tgid;
+			ttc->tc = tc;
+		}
+		/*
+		 * sort ttc
+		 */
+		HeapSort(tt->ttc_array, RUNNING_TASKS());
+		/*
+		 * set ttc->tc->tgid-task_context_index
+		 */
+		ttc = tt->ttc_array;
+		for (i = 0; i < RUNNING_TASKS(); i++, ttc++)
+		{
+			ttc->tc->tgid_task_context_index = i;
+		}
+	} else 
+		return;
+}
+
+/*
+ * set the const value of filepages and anonpages 
+ * according to MM_FILEPAGES and MM_ANONPAGES.
+ */
+void 
+set_pages(void)
+{
+	long anonpages, filepages;
+	if (VALID_MEMBER(mm_struct_rss))
+		return;
+	if (VALID_MEMBER(mm_struct_rss_stat)) 
+	{
+		if (!enumerator_value("MM_FILEPAGES", &filepages) ||
+		!enumerator_value("MM_ANONPAGES", &anonpages)) 
+		{
+			filepages = 0;
+			anonpages = 1;
+		}
+		tt->filepages = filepages;
+		tt->anonpages = anonpages;
+	} else {
+		return;
+	}
+}
 
 static void
 show_ps(ulong flag, struct psinfo *psi)
-- 
1.7.1


--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux