[PATCH] Improve the ps performance for vmcores with large number of threads

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

 



Previously, the ps command will iterate over all threads which
have the same tgid, to accumulate their rss value, in order to
get a thread/process's final rss value as part of the final output.

For non-live systems, the rss accumulation values are identical for
threads which have the same tgid, so there is no need to do the
iteration and accumulation repeatly, thus a lot of readmem calls are
skipped. Otherwise it will be the performance bottleneck if the
vmcores have a large number of threads.

In this patch, the rss accumulation value will be stored in a cache,
next time a thread with the same tgid will take it directly without
the iteration.

For example, we can monitor the performance issue when a vmcore has
~65k processes, most of which are threads for several specific
processes. Without the patch, it will take ~7h for ps command
to finish. With the patch, ps command will finish in 1min.

Signed-off-by: Tao Liu <ltao@xxxxxxxxxx>
---
 defs.h   |  1 +
 memory.c | 67 ++++++++++++++++++++++++++++++--------------------------
 task.c   |  1 +
 3 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/defs.h b/defs.h
index b63741c..55600d5 100644
--- a/defs.h
+++ b/defs.h
@@ -829,6 +829,7 @@ struct task_context {                     /* context stored for each task */
 struct tgid_context {               /* tgid and task stored for each task */
 	ulong tgid;
 	ulong task;
+	long rss_cache;
 };
 
 struct task_table {                      /* kernel/local task table data */
diff --git a/memory.c b/memory.c
index 5af45fd..b930933 100644
--- a/memory.c
+++ b/memory.c
@@ -4665,7 +4665,7 @@ void
 get_task_mem_usage(ulong task, struct task_mem_usage *tm)
 {
 	struct task_context *tc;
-	long rss = 0;
+	long rss = 0, rss_cache = 0;
 
 	BZERO(tm, sizeof(struct task_mem_usage));
 
@@ -4730,38 +4730,43 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
 					(last->tgid == (last + 1)->tgid))
 					last++;
 
-				while (first <= last)
-				{
-					/* count 0 -> filepages */
-					if (!readmem(first->task +
-						OFFSET(task_struct_rss_stat) +
-						OFFSET(task_rss_stat_count), KVADDR,
-						&sync_rss,
-						sizeof(int),
-						"task_struct rss_stat MM_FILEPAGES",
-						RETURN_ON_ERROR))
-							continue;
-
-					rss += sync_rss;
-
-					/* count 1 -> anonpages */
-					if (!readmem(first->task +
-						OFFSET(task_struct_rss_stat) +
-						OFFSET(task_rss_stat_count) +
-						sizeof(int),
-						KVADDR, &sync_rss,
-						sizeof(int),
-						"task_struct rss_stat MM_ANONPAGES",
-						RETURN_ON_ERROR))
-							continue;
-
-					rss += sync_rss;
-
-					if (first == last)
-						break;
-					first++;
+				/* We will use rss_cache only for dumpfile */
+				if (ACTIVE() || last->rss_cache == UNINITIALIZED) {
+					while (first <= last)
+					{
+						/* count 0 -> filepages */
+						if (!readmem(first->task +
+							OFFSET(task_struct_rss_stat) +
+							OFFSET(task_rss_stat_count), KVADDR,
+							&sync_rss,
+							sizeof(int),
+							"task_struct rss_stat MM_FILEPAGES",
+							RETURN_ON_ERROR))
+								continue;
+
+						rss_cache += sync_rss;
+
+						/* count 1 -> anonpages */
+						if (!readmem(first->task +
+							OFFSET(task_struct_rss_stat) +
+							OFFSET(task_rss_stat_count) +
+							sizeof(int),
+							KVADDR, &sync_rss,
+							sizeof(int),
+							"task_struct rss_stat MM_ANONPAGES",
+							RETURN_ON_ERROR))
+								continue;
+
+						rss_cache += sync_rss;
+
+						if (first == last)
+							break;
+						first++;
+					}
+					last->rss_cache = rss_cache;
 				}
 
+				rss += last->rss_cache;
 				tt->last_tgid = last;
 			}
 		}
diff --git a/task.c b/task.c
index 263a834..9868a6e 100644
--- a/task.c
+++ b/task.c
@@ -2947,6 +2947,7 @@ add_context(ulong task, char *tp)
 	tg = tt->tgid_array + tt->running_tasks;
 	tg->tgid = *tgid_addr;
 	tg->task = task;
+	tg->rss_cache = UNINITIALIZED;
 
         if (do_verify && !verify_task(tc, do_verify)) {
 		error(INFO, "invalid task address: %lx\n", tc->task);
-- 
2.33.1

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




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

 

Powered by Linux