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

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