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