Hello Dave,

These two patches are used to improve the performance of "kmem -s
[address]".

Current code need to search all kmem_caches twice. It is a waste of
time. With my patch, the address is sent to "dump_kmem_cache" function
to make the second search be restricted to the kmem_cache found in the
first search. It means the second search is neglected.

I have implemented the improvement for three types of kmem_cache. The
search for "slub" does not waste that much time as its peers, so I did
not modify the code related to "slub". Additionally, I only get the
environment to test my first patch, so the second patch has not been tested.

Here is the statistic of my test on RHEL6.2 x86_64, the vmcore used for
testing has about 150000 kmem_caches
commands in file:
1. only 'quit'

origin code : about 36s
with patch  : about 36s

2. 1 time of searching the 100000th kmem_cache
origin code : about 59s
with patch  : about 39s

3. 100 times of searching the 100000th kmem_cache
origin code : about 38min30s
with patch  : about 5min


p.s.
If I create a kmem_cache called "list", a little confusion may happen
when using "kmem -s list". I am wondering is it necessary to introduce
an another option replacing list to avoid such collision.

-- 
--
Regards
Qiao Nuohan

diff --git a/memory.c b/memory.c
index 95eefc9..2ec44ab 100755
--- a/memory.c
+++ b/memory.c
@@ -4091,6 +4091,7 @@ cmd_kmem(void)
                                        error(FATAL, 
                                  "only one kmem_cache reference is allowed\n");
                                meminfo.reqname = p1;
+                               meminfo.cache = value[i];
                                if ((i+1) == spec_addr) { /* done? */ 
                                        if (meminfo.calls++)
                                                fprintf(fp, "\n");
@@ -7589,15 +7590,12 @@ is_kmem_cache_addr(ulong vaddr, char *kbuf)
        cache_buf = GETBUF(SIZE(kmem_cache_s));
 
         do {
-               readmem(cache, KVADDR, cache_buf, SIZE(kmem_cache_s),
-                       "kmem_cache buffer", FAULT_ON_ERROR);
 
                if (cache == vaddr) {
                        if (vt->kmem_cache_namelen) {
-                               BCOPY(cache_buf+name_offset, kbuf, 
-                                       vt->kmem_cache_namelen);
+                               readmem(cache+name_offset, KVADDR, kbuf, 
vt->kmem_cache_namelen, "name array", FAULT_ON_ERROR);
                        } else {
-                               name = ULONG(cache_buf + name_offset);
+                               readmem(cache+name_offset, KVADDR, &name, 
sizeof(name), "name", FAULT_ON_ERROR);
                                if (!read_string(name, kbuf, BUFSIZE-1)) {
                                        if (vt->flags & 
                                          (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2))
@@ -7615,7 +7613,8 @@ is_kmem_cache_addr(ulong vaddr, char *kbuf)
                        return kbuf;
                }
 
-               cache = ULONG(cache_buf + next_offset);
+               readmem(cache+next_offset, KVADDR, &cache, sizeof(long),
+                       "kmem_cache_s next", FAULT_ON_ERROR);
 
                if (vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2))
                        cache -= next_offset;
@@ -8733,9 +8732,15 @@ dump_kmem_cache_percpu_v2(struct meminfo *si)
 
        cnt = 0;
 
-        get_symbol_data("cache_chain", sizeof(ulong), &si->cache);
-        si->cache -= OFFSET(kmem_cache_s_next);
-        cache_end = symbol_value("cache_chain");
+       if (si->cache) {
+               readmem(si->cache+OFFSET(kmem_cache_s_next), 
+                       KVADDR, &cache_end, sizeof(ulong),
+                       "kmem_cache_s next", FAULT_ON_ERROR);
+       } else {
+               get_symbol_data("cache_chain", sizeof(ulong), &si->cache);
+               si->cache -= OFFSET(kmem_cache_s_next);
+               cache_end = symbol_value("cache_chain");
+       }
 
        if (si->flags & ADDRESS_SPECIFIED) {
                if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
diff --git a/memory.c b/memory.c
index 2ec44ab..27a5346 100755
--- a/memory.c
+++ b/memory.c
@@ -8303,7 +8303,13 @@ dump_kmem_cache(struct meminfo *si)
 
        si->addrlist = (ulong *)GETBUF((vt->kmem_max_c_num+1) * sizeof(ulong));
        cnt = 0;
-       si->cache = cache_cache = symbol_value("cache_cache");
+       if (si->cache) {
+               readmem(si->cache+OFFSET(kmem_cache_s_c_nextp),
+                       KVADDR, &cache_cache, sizeof(ulong),
+                       "kmem_cache next", FAULT_ON_ERROR);
+       } else {
+               si->cache = cache_cache = symbol_value("cache_cache");
+       }
 
        if (si->flags & ADDRESS_SPECIFIED) {
                if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
@@ -8509,7 +8515,13 @@ dump_kmem_cache_percpu_v1(struct meminfo *si)
                        GETBUF(vt->kmem_max_limit * sizeof(ulong)); 
 
        cnt = 0;
-       si->cache = cache_cache = symbol_value("cache_cache");
+       if (si->cache) {
+               readmem(si->cache+OFFSET(kmem_cache_s_next), 
+                       KVADDR, &cache_cache, sizeof(ulong),
+                       "kmem_cache_s next", FAULT_ON_ERROR);
+       } else {
+               si->cache = cache_cache = symbol_value("cache_cache");
+       }
 
        if (si->flags & ADDRESS_SPECIFIED) {
                if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to