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 <[email protected]>
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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to