Blame SOURCES/0009-Improve-the-ps-performance-for-vmcores-with-large-nu.patch

412566
From d52cccfaa96ed6f61ff9d53da88715296e31db80 Mon Sep 17 00:00:00 2001
412566
From: Tao Liu <ltao@redhat.com>
412566
Date: Fri, 21 Jan 2022 13:43:09 +0800
412566
Subject: [PATCH 09/11] Improve the ps performance for vmcores with large
412566
 number of threads
412566
412566
Previously, the ps command will iterate over all threads which
412566
have the same tgid, to accumulate their rss value, in order to
412566
get a thread/process's final rss value as part of the final output.
412566
412566
For non-live systems, the rss accumulation values are identical for
412566
threads which have the same tgid, so there is no need to do the
412566
iteration and accumulation repeatly, thus a lot of readmem calls are
412566
skipped. Otherwise it will be the performance bottleneck if the
412566
vmcores have a large number of threads.
412566
412566
In this patch, the rss accumulation value will be stored in a cache,
412566
next time a thread with the same tgid will take it directly without
412566
the iteration.
412566
412566
For example, we can monitor the performance issue when a vmcore has
412566
~65k processes, most of which are threads for several specific
412566
processes. Without the patch, it will take ~7h for ps command
412566
to finish. With the patch, ps command will finish in 1min.
412566
412566
Signed-off-by: Tao Liu <ltao@redhat.com>
412566
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
412566
---
412566
 defs.h   |  1 +
412566
 memory.c | 70 +++++++++++++++++++++++++++++++-------------------------
412566
 task.c   |  1 +
412566
 3 files changed, 41 insertions(+), 31 deletions(-)
412566
412566
diff --git a/defs.h b/defs.h
412566
index 41b6cbc6cc85..77e76f27cddb 100644
412566
--- a/defs.h
412566
+++ b/defs.h
412566
@@ -830,6 +830,7 @@ struct task_context {                     /* context stored for each task */
412566
 struct tgid_context {               /* tgid and task stored for each task */
412566
 	ulong tgid;
412566
 	ulong task;
412566
+	long rss_cache;
412566
 };
412566
 
412566
 struct task_table {                      /* kernel/local task table data */
412566
diff --git a/memory.c b/memory.c
412566
index 5af45fd7d834..e80c59ea4534 100644
412566
--- a/memory.c
412566
+++ b/memory.c
412566
@@ -4665,7 +4665,7 @@ void
412566
 get_task_mem_usage(ulong task, struct task_mem_usage *tm)
412566
 {
412566
 	struct task_context *tc;
412566
-	long rss = 0;
412566
+	long rss = 0, rss_cache = 0;
412566
 
412566
 	BZERO(tm, sizeof(struct task_mem_usage));
412566
 
412566
@@ -4730,38 +4730,46 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
412566
 					(last->tgid == (last + 1)->tgid))
412566
 					last++;
412566
 
412566
-				while (first <= last)
412566
-				{
412566
-					/* count 0 -> filepages */
412566
-					if (!readmem(first->task +
412566
-						OFFSET(task_struct_rss_stat) +
412566
-						OFFSET(task_rss_stat_count), KVADDR,
412566
-						&sync_rss,
412566
-						sizeof(int),
412566
-						"task_struct rss_stat MM_FILEPAGES",
412566
-						RETURN_ON_ERROR))
412566
-							continue;
412566
-
412566
-					rss += sync_rss;
412566
-
412566
-					/* count 1 -> anonpages */
412566
-					if (!readmem(first->task +
412566
-						OFFSET(task_struct_rss_stat) +
412566
-						OFFSET(task_rss_stat_count) +
412566
-						sizeof(int),
412566
-						KVADDR, &sync_rss,
412566
-						sizeof(int),
412566
-						"task_struct rss_stat MM_ANONPAGES",
412566
-						RETURN_ON_ERROR))
412566
-							continue;
412566
-
412566
-					rss += sync_rss;
412566
-
412566
-					if (first == last)
412566
-						break;
412566
-					first++;
412566
+				/*
412566
+				 * Using rss cache for dumpfile is more beneficial than live debug
412566
+				 * because its value never changes in dumpfile.
412566
+				 */
412566
+				if (ACTIVE() || last->rss_cache == UNINITIALIZED) {
412566
+					while (first <= last)
412566
+					{
412566
+						/* count 0 -> filepages */
412566
+						if (!readmem(first->task +
412566
+							OFFSET(task_struct_rss_stat) +
412566
+							OFFSET(task_rss_stat_count), KVADDR,
412566
+							&sync_rss,
412566
+							sizeof(int),
412566
+							"task_struct rss_stat MM_FILEPAGES",
412566
+							RETURN_ON_ERROR))
412566
+								continue;
412566
+
412566
+						rss_cache += sync_rss;
412566
+
412566
+						/* count 1 -> anonpages */
412566
+						if (!readmem(first->task +
412566
+							OFFSET(task_struct_rss_stat) +
412566
+							OFFSET(task_rss_stat_count) +
412566
+							sizeof(int),
412566
+							KVADDR, &sync_rss,
412566
+							sizeof(int),
412566
+							"task_struct rss_stat MM_ANONPAGES",
412566
+							RETURN_ON_ERROR))
412566
+								continue;
412566
+
412566
+						rss_cache += sync_rss;
412566
+
412566
+						if (first == last)
412566
+							break;
412566
+						first++;
412566
+					}
412566
+					last->rss_cache = rss_cache;
412566
 				}
412566
 
412566
+				rss += last->rss_cache;
412566
 				tt->last_tgid = last;
412566
 			}
412566
 		}
412566
diff --git a/task.c b/task.c
412566
index a79ed0d96fb5..864c838637ee 100644
412566
--- a/task.c
412566
+++ b/task.c
412566
@@ -2947,6 +2947,7 @@ add_context(ulong task, char *tp)
412566
 	tg = tt->tgid_array + tt->running_tasks;
412566
 	tg->tgid = *tgid_addr;
412566
 	tg->task = task;
412566
+	tg->rss_cache = UNINITIALIZED;
412566
 
412566
         if (do_verify && !verify_task(tc, do_verify)) {
412566
 		error(INFO, "invalid task address: %lx\n", tc->task);
412566
-- 
412566
2.20.1
412566