Re: improve ps performance

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

 




----- Original Message -----
> Hello Dave,
> 
> 
> I have modified the patch by your idea.
> 
> Please check.
> 
>    Thanks,
>      Pan
 
Hello Pan,

Thanks for updating this latest patch -- nice work!  

I have made a few changes:

(1) a few name changes for clarity's sake,
(2) moved the new task_table members to the end of the structure
    so as to not break extension modules that use it,
(3) fixed the malloc() memory leak in get_task_mem_usage(), 
(4) fixed the access of the tgid in store_context(), which needs to be
    accessed and stored as a pid_t and not a ulong, 
(5) added the "help -T" output to show the new fields in the task_table,
(6) and probably some other stuff that I've forgotten...

But for the most part I have left things functionally the same.  

I've attached the end result, and will continue testing it tomorrow.

Thanks,
  Dave
 
--- main.c.orig	2014-07-31 14:35:05.941461775 -0400
+++ main.c	2014-09-09 15:47:09.250993934 -0400
@@ -800,6 +800,7 @@ reattempt:
 			} else if (!(pc->flags & MINIMAL_MODE)) {
 				tt->refresh_task_table();
 				sort_context_array();
+				sort_tgid_array();	
 			}
 		}
                 if (!STREQ(pc->curcmd, pc->program_name))
--- memory.c.orig	2014-09-04 16:48:14.430966493 -0400
+++ memory.c	2014-09-09 16:32:13.103886795 -0400
@@ -225,6 +225,7 @@ static int next_module_vaddr(ulong, ulon
 static int next_identity_mapping(ulong, ulong *);
 static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong,
 	struct reference *);
+static void rss_page_types_init(void);
 static int dump_swap_info(ulong, ulong *, ulong *);
 static void swap_info_init(void);
 static char *get_swapdev(ulong, char *);
@@ -1070,6 +1071,8 @@ vm_init(void)
 
 	page_flags_init();
 
+	rss_page_types_init();
+
 	vt->flags |= VM_INIT;
 }
 
@@ -4076,6 +4079,31 @@ in_user_stack(ulong task, ulong vaddr)
 }
 
 /*
+ * Set the const value of filepages and anonpages 
+ * according to MM_FILEPAGES and MM_ANONPAGES.
+ */
+void 
+rss_page_types_init(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;
+	}
+}
+
+/*
  *  Fill in the task_mem_usage structure with the RSS, virtual memory size,
  *  percent of physical memory being used, and the mm_struct address.
  */
@@ -4112,11 +4140,8 @@ get_task_mem_usage(ulong task, struct ta
 		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) +
@@ -4129,19 +4154,33 @@ get_task_mem_usage(ulong task, struct ta
 
 		/* Check whether SPLIT_RSS_COUNTING is enabled */
 		if (VALID_MEMBER(task_struct_rss_stat)) {
-			int i, sync_rss;
-			ulong tgid;
-			struct task_context *tc1;
-
-			tgid = task_tgid(task);
-
-			tc1 = FIRST_CONTEXT();
-			for (i = 0; i < RUNNING_TASKS(); i++, tc1++) {
-				if (task_tgid(tc1->task) != tgid)
-					continue;
+			int sync_rss;
+			struct tgid_context tgid, *tgid_array, *tg, *first, *last;
 
+			tgid_array = tt->tgid_array;
+			tgid.tgid = task_tgid(task);
+
+			tg = (struct tgid_context *)bsearch(&tgid, tgid_array, RUNNING_TASKS(), 
+				sizeof(struct tgid_context), sort_by_tgid);
+			if (tg == NULL)
+				error(FATAL, "bsearch for tgid failed: task: %lx tgid: %ld\n", 
+					task, tgid.tgid);
+
+			/* find the first element which has the same tgid */
+			first = tg;
+			while ((first > tgid_array) && ((first - 1)->tgid == first->tgid)) 
+				first--;
+
+			/* find the last element which have same tgid */
+			last = tg;
+			while ((last < (tgid_array + (RUNNING_TASKS() - 1))) && 
+				(last->tgid == (last + 1)->tgid))
+				last++;
+
+			while (first <= last)
+			{
 				/* count 0 -> filepages */
-				if (!readmem(tc1->task +
+				if (!readmem(first->task +
 					OFFSET(task_struct_rss_stat) +
 					OFFSET(task_rss_stat_count), KVADDR,
 					&sync_rss,
@@ -4153,7 +4192,7 @@ get_task_mem_usage(ulong task, struct ta
 				rss += sync_rss;
 
 				/* count 1 -> anonpages */
-				if (!readmem(tc1->task +
+				if (!readmem(first->task +
 					OFFSET(task_struct_rss_stat) +
 					OFFSET(task_rss_stat_count) +
 					sizeof(int),
@@ -4164,6 +4203,10 @@ get_task_mem_usage(ulong task, struct ta
 						continue;
 
 				rss += sync_rss;
+
+				if(first == last)
+					break;
+				first++;
 			}
 		}
 
--- task.c.orig	2014-06-02 17:13:47.298954087 -0400
+++ task.c	2014-09-09 16:46:11.751853564 -0400
@@ -493,6 +493,7 @@ task_init(void)
 	}
 
 	sort_context_array();
+	sort_tgid_array();
 
 	if (pc->flags & SILENT)
 		initialize_task_state();
@@ -639,6 +640,11 @@ allocate_task_space(int cnt)
                     malloc(cnt * sizeof(struct task_context))))
                         error(FATAL, "cannot malloc context array (%d tasks)",
                                 cnt);
+		if (!(tt->tgid_array = (struct tgid_context *)
+                    malloc(cnt * sizeof(struct tgid_context))))
+                        error(FATAL, "cannot malloc tgid array (%d tasks)",
+                                cnt);
+
 	} else {
                 if (!(tt->task_local = (void *)
 		    realloc(tt->task_local, cnt * sizeof(void *)))) 
@@ -652,6 +658,13 @@ allocate_task_space(int cnt)
                         error(FATAL,
                             "%scannot realloc context array (%d tasks)",
 	                	(pc->flags & RUNTIME) ? "" : "\n", cnt);
+
+		 if (!(tt->tgid_array = (struct tgid_context *)
+                    realloc(tt->tgid_array, 
+		    cnt * sizeof(struct tgid_context)))) 
+                        error(FATAL,
+                            "%scannot realloc tgid array (%d tasks)",
+	                	(pc->flags & RUNTIME) ? "" : "\n", cnt);
 	}
 }
 
@@ -2276,13 +2289,14 @@ retry_active:
 static struct task_context *
 store_context(struct task_context *tc, ulong task, char *tp)
 {
-        pid_t *pid_addr;
+        pid_t *pid_addr, *tgid_addr;
         char *comm_addr;
         int *processor_addr;
         ulong *parent_addr;
         ulong *mm_addr;
         int has_cpu;
 	int do_verify;
+	struct tgid_context *tg;
 
 	processor_addr = NULL;
 
@@ -2305,6 +2319,7 @@ store_context(struct task_context *tc, u
 		tc = tt->context_array + tt->running_tasks;
 
         pid_addr = (pid_t *)(tp + OFFSET(task_struct_pid));
+	tgid_addr = (pid_t *)(tp + OFFSET(task_struct_tgid));
         comm_addr = (char *)(tp + OFFSET(task_struct_comm));
 	if (tt->flags & THREAD_INFO) {
 		tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info));
@@ -2330,6 +2345,14 @@ store_context(struct task_context *tc, u
         tc->task = task;
         tc->tc_next = NULL;
 
+	/*
+	 *  Fill a tgid_context structure with the data from 
+	 *  the incoming task.
+	 */
+	tg = tt->tgid_array + tt->running_tasks;
+	tg->tgid = *tgid_addr;
+	tg->task = task;
+
         if (do_verify && !verify_task(tc, do_verify)) {
 		error(INFO, "invalid task address: %lx\n", tc->task);
                 BZERO(tc, sizeof(struct task_context));
@@ -2445,6 +2468,31 @@ sort_context_array_by_last_run(void)
 }
 
 /*
+ *  Set the tgid_context array by tgid number.
+ */
+void
+sort_tgid_array(void)
+{
+	if (VALID_MEMBER(mm_struct_rss) || (!VALID_MEMBER(task_struct_rss_stat)))
+		return;
+
+	qsort((void *)tt->tgid_array, (size_t)tt->running_tasks,
+		sizeof(struct tgid_context), sort_by_tgid);
+}
+
+int
+sort_by_tgid(const void *arg1, const void *arg2)
+{
+	struct tgid_context *t1, *t2;
+
+	t1 = (struct tgid_context *)arg1;
+	t2 = (struct tgid_context *)arg2;
+
+	return (t1->tgid < t2->tgid ? -1 :
+		t1->tgid == t2->tgid ? 0 : 1);
+}
+
+/*
  *  Keep a stash of the last task_struct accessed.  Chances are it will
  *  be hit several times before the next task is accessed.
  */
@@ -6557,6 +6605,7 @@ dump_task_table(int verbose)
 {
 	int i, j, more, nr_cpus;
 	struct task_context *tc;
+	struct tgid_context *tg;
 	char buf[BUFSIZE];
 	int others, wrap, flen;
 
@@ -6577,6 +6626,7 @@ dump_task_table(int verbose)
 		fprintf(fp, "          .tc_next: %lx\n", (ulong)tc->tc_next);
 	}
 	fprintf(fp, "     context_array: %lx\n",  (ulong)tt->context_array);
+	fprintf(fp, "        tgid_array: %lx\n",  (ulong)tt->tgid_array);
 	fprintf(fp, "refresh_task_table: ");
 	if (tt->refresh_task_table == refresh_fixed_task_table)
 		fprintf(fp, "refresh_fixed_task_table()\n");
@@ -6671,6 +6721,8 @@ dump_task_table(int verbose)
 	fprintf(fp, "       task_struct: %lx\n", (ulong)tt->task_struct);
 	fprintf(fp, "         mm_struct: %lx\n", (ulong)tt->mm_struct);
 	fprintf(fp, "       init_pid_ns: %lx\n", tt->init_pid_ns);
+	fprintf(fp, "         filepages: %ld\n", tt->filepages);
+	fprintf(fp, "         anonpages: %ld\n", tt->anonpages);
 
 
 	wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4;
@@ -6886,6 +6938,13 @@ dump_task_table(int verbose)
 				i, tc->task, tc->pid, tc->processor, tc->ptask,
 				(ulong)tc->mm_struct, tc->comm); 
 	}
+
+        fprintf(fp, "\nINDEX       TASK       TGID  (COMM)\n");
+	for (i = 0; i < RUNNING_TASKS(); i++) {
+		tg = &tt->tgid_array[i];
+		tc = task_to_context(tg->task);
+		fprintf(fp, "[%3d] %lx %ld (%s)\n", i, tg->task, tg->tgid, tc->comm);
+	}
 }
 
 /*
--- defs.h.orig	2014-07-31 14:35:48.977460276 -0400
+++ defs.h	2014-09-09 15:46:39.315995120 -0400
@@ -762,6 +762,11 @@ struct task_context {
 	struct task_context *tc_next;
 };
 
+struct tgid_context {               /* tgid and task stored for each task */
+	ulong tgid;
+	ulong task;
+};
+
 struct task_table {                      /* kernel/local task table data */
 	struct task_context *current;
 	struct task_context *context_array;
@@ -795,6 +800,9 @@ struct task_table {
 	char *thread_info;
 	char *mm_struct;
 	ulong init_pid_ns;
+	struct tgid_context *tgid_array;
+	long filepages;
+	long anonpages;
 };
 
 #define TASK_INIT_DONE       (0x1)
@@ -4831,6 +4839,8 @@ ulong generic_get_stackbase(ulong);
 ulong generic_get_stacktop(ulong);
 void dump_task_table(int);
 void sort_context_array(void);
+void sort_tgid_array(void);
+int sort_by_tgid(const void *, const void *);
 int in_irq_ctx(ulonglong, int, ulong);
 
 /*
--
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