From: Paulo Marques <pmarques@grupopie.com>
To: Ingo Molnar <mingo@elte.hu>
Cc: Andi Kleen <ak@muc.de>, linux-kernel@vger.kernel.org
Subject: Re: [patch] Latency Tracer, voluntary-preempt-2.6.8-rc4-O6
Date: Sat, 14 Aug 2004 05:50:50 +0100 [thread overview]
Message-ID: <411D9A2A.1000202@grupopie.com> (raw)
In-Reply-To: <20040813135109.GA20638@elte.hu>
[-- Attachment #1: Type: text/plain, Size: 2156 bytes --]
Ingo Molnar wrote:
>...
>
>>With binary search you would need to backward search to find the stem
>>for the stem compression. It's probably doable, but would be a bit
>>ugly I guess.
>
>
> yeah. Maybe someone will find the time to improve the algorithm. But
> it's not a highprio thing.
Well, I found some time and decided to give it a go :)
I first built a small test program that could provide the same symbol
data to the lookup function, so that I could test using a user space app.
This way I could benchmark both the original algorithm and any
improvement I could make, and do it confortably from user space.
The original algorithm took, on average, 1340us per lookup on my P4
2.8GHz. The compile settings for the test are not the same on the
kernel, so this can be only compared against other results from the same
setup.
With the attached patch it takes 14us per lookup. This is almost a 100x
improvement.
The largest portion of the time it took to do a lookup, was the
decompression of the symbol names. It seemed a waste of time to keep
strcpy'ing over the result lots of names that would probably not
contribute to the final name.
With the strcpy's out, the speed-up was around 5x, but even then,
looking sequentially for the symbol name was still slow.
The final algorithm pre-calculates markers on the compressed symbols so
that the search time is almost divided by the number of markers.
There are still a few issues with this approach. The biggest issue is
that this is clearly a speed/space trade-off, and maybe we don't want to
waste the space on a code path that is not supposed to be "hot". If this
is the case, I can make a smaller patch, that fixes just the name
"decompression" strcpy's.
As always, any comments will be greatly appreciated.
Just one side note: gcc gives a warning about 2 variables that might be
used before initialization. I know they are not, and it didn't seem a
good idea to put extra code just to shut up gcc. What is the standard
way to convince gcc that those vars are ok?
--
Paulo Marques - www.grupopie.com
"In a world without walls and fences who needs windows and gates?"
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 4396 bytes --]
--- kernel/kallsyms.c.old 2004-08-14 00:28:58.000000000 +0100
+++ kernel/kallsyms.c 2004-08-14 05:10:09.873194752 +0100
@@ -22,6 +22,13 @@ extern char kallsyms_names[] __attribute
/* Defined by the linker script. */
extern char _stext[], _etext[], _sinittext[], _einittext[];
+/* auxiliary markers to speed up symbol lookup */
+#define KALLSYMS_STEM_MARKS 8
+
+static int kallsyms_stem_mark_idx[KALLSYMS_STEM_MARKS];
+static char *kallsyms_stem_mark[KALLSYMS_STEM_MARKS];
+
+
static inline int is_kernel_inittext(unsigned long addr)
{
if (addr >= (unsigned long)_sinittext
@@ -56,13 +63,42 @@ unsigned long kallsyms_lookup_name(const
return module_kallsyms_lookup_name(name);
}
+/* build markers into the compressed symbol table, so that lookups can be faster */
+static void build_stem_marks(void)
+{
+ char *name = kallsyms_names;
+ int i, mark_cnt;
+
+ unsigned prefix;
+
+ mark_cnt = 0;
+ for (i = 0 ; i < kallsyms_num_syms; i++) {
+ prefix=*name;
+ if (prefix == 0) {
+ /* if this is the first 0-prefix stem in the desired interval */
+ if(i > (mark_cnt + 1) * (kallsyms_num_syms / (KALLSYMS_STEM_MARKS + 1)) &&
+ kallsyms_stem_mark_idx[mark_cnt]==0) {
+ kallsyms_stem_mark[mark_cnt] = name;
+ kallsyms_stem_mark_idx[mark_cnt] = i;
+ mark_cnt++;
+ if(mark_cnt >= KALLSYMS_STEM_MARKS) break;
+ }
+ }
+ do {
+ name++;
+ } while(*name);
+ name ++;
+ }
+}
/* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname, char *namebuf)
{
- unsigned long i, best = 0;
+ unsigned long i, last_0idx;
+ unsigned long mark, low, high, mid;
+ char *last_0prefix;
/* This kernel should never had been booted. */
BUG_ON(!kallsyms_addresses);
@@ -72,39 +108,67 @@ const char *kallsyms_lookup(unsigned lon
if (is_kernel_text(addr) || is_kernel_inittext(addr)) {
unsigned long symbol_end;
- char *name = kallsyms_names;
+ char *name;
- /* They're sorted, we could be clever here, but who cares? */
- for (i = 0; i < kallsyms_num_syms; i++) {
- if (kallsyms_addresses[i] > kallsyms_addresses[best] &&
- kallsyms_addresses[i] <= addr)
- best = i;
+ /* do a binary search on the sorted kallsyms_addresses array */
+ low = 0;
+ high = kallsyms_num_syms;
+ while( high-low > 1 ) {
+ mid = (low + high) / 2;
+ if( kallsyms_addresses[mid] <= addr ) low = mid;
+ else high = mid;
}
/* Grab name */
- for (i = 0; i <= best; i++) {
- unsigned prefix = *name++;
- strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix);
- name += strlen(name) + 1;
- }
+ i = 0;
+ name = kallsyms_names;
- /* At worst, symbol ends at end of section. */
- if (is_kernel_inittext(addr))
- symbol_end = (unsigned long)_einittext;
- else
- symbol_end = (unsigned long)_etext;
+ if(kallsyms_stem_mark_idx[0]==0)
+ build_stem_marks();
+
+ for(mark = 0; mark < KALLSYMS_STEM_MARKS; mark++) {
+ if( low >= kallsyms_stem_mark_idx[mark] ) {
+ i = kallsyms_stem_mark_idx[mark];
+ name = kallsyms_stem_mark[mark];
+ }
+ else break;
+ }
- /* Search for next non-aliased symbol */
- for (i = best+1; i < kallsyms_num_syms; i++) {
- if (kallsyms_addresses[i] > kallsyms_addresses[best]) {
- symbol_end = kallsyms_addresses[i];
- break;
+ /* find the last stem before the actual symbol that as 0 prefix */
+ unsigned prefix;
+ for (; i <= low; i++) {
+ prefix=*name;
+ if (prefix == 0) {
+ last_0prefix = name;
+ last_0idx = i;
}
+ do {
+ name++;
+ } while(*name);
+ name ++;
}
- *symbolsize = symbol_end - kallsyms_addresses[best];
+ /* build the name from there */
+ name = last_0prefix;
+ for (i = last_0idx; i <= low; i++) {
+ prefix = *name++;
+ strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix);
+ name += strlen(name) + 1;
+ }
+
+ if(low == kallsyms_num_syms - 1) {
+ /* At worst, symbol ends at end of section. */
+ if (is_kernel_inittext(addr))
+ symbol_end = (unsigned long)_einittext;
+ else
+ symbol_end = (unsigned long)_etext;
+ }
+ else
+ symbol_end = kallsyms_addresses[low + 1];
+
+ *symbolsize = symbol_end - kallsyms_addresses[low];
*modname = NULL;
- *offset = addr - kallsyms_addresses[best];
+ *offset = addr - kallsyms_addresses[low];
return namebuf;
}
next prev parent reply other threads:[~2004-08-14 4:51 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <2m9bF-kH-13@gated-at.bofh.it>
[not found] ` <2m9EG-Js-5@gated-at.bofh.it>
[not found] ` <2md5B-36u-11@gated-at.bofh.it>
[not found] ` <2mkTt-BZ-11@gated-at.bofh.it>
[not found] ` <2nrJd-7Dx-19@gated-at.bofh.it>
[not found] ` <2ouFe-2vz-63@gated-at.bofh.it>
[not found] ` <2rfT9-5wi-17@gated-at.bofh.it>
[not found] ` <2rF1c-6Iy-7@gated-at.bofh.it>
[not found] ` <2sxEs-46P-1@gated-at.bofh.it>
[not found] ` <2sCkH-7i5-15@gated-at.bofh.it>
[not found] ` <2sHu9-2EW-31@gated-at.bofh.it>
2004-08-13 12:08 ` [patch] Latency Tracer, voluntary-preempt-2.6.8-rc4-O6 Andi Kleen
2004-08-13 12:15 ` Ingo Molnar
2004-08-13 12:16 ` Ingo Molnar
2004-08-13 12:18 ` Andi Kleen
2004-08-13 13:51 ` Ingo Molnar
2004-08-14 4:50 ` Paulo Marques [this message]
2004-08-14 5:01 ` Lee Revell
2004-08-14 13:35 ` Paulo Marques
2004-08-14 16:49 ` Lee Revell
2004-08-14 7:15 ` Ingo Molnar
2004-08-14 13:32 ` Paulo Marques
2004-08-14 12:17 ` Keith Owens
2004-08-15 0:21 ` Paulo Marques
2004-08-17 12:14 ` Paulo Marques
2004-08-17 13:05 ` Keith Owens
2004-08-17 14:02 ` Paulo Marques
2004-08-17 16:23 ` Sam Ravnborg
2004-08-17 17:55 ` Ingo Molnar
2004-08-17 18:17 ` Paulo Marques
2004-08-14 12:41 ` Andi Kleen
2004-08-14 13:45 ` Paulo Marques
2004-07-26 8:23 preempt-timing-2.6.8-rc1 Ingo Molnar
2004-07-26 8:29 ` preempt-timing-2.6.8-rc1 Lee Revell
2004-07-26 8:35 ` [patch] voluntary-preempt-2.6.8-rc2-J3 Ingo Molnar
2004-07-26 9:00 ` Lee Revell
2004-07-26 12:40 ` Ingo Molnar
2004-07-26 20:47 ` [patch] voluntary-preempt-2.6.8-rc2-J7 Ingo Molnar
2004-07-29 22:26 ` [patch] voluntary-preempt-2.6.8-rc2-M5 Ingo Molnar
2004-08-01 19:30 ` [patch] voluntary-preempt-2.6.8-rc2-O2 Ingo Molnar
2004-08-09 10:46 ` [patch] voluntary-preempt-2.6.8-rc3-O4 Ingo Molnar
2004-08-10 13:26 ` [patch] voluntary-preempt-2.6.8-rc3-O5 Ingo Molnar
2004-08-12 23:51 ` [patch] Latency Tracer, voluntary-preempt-2.6.8-rc4-O6 Ingo Molnar
2004-08-13 1:25 ` Lee Revell
2004-08-13 1:31 ` Lee Revell
2004-08-13 2:39 ` Lee Revell
2004-08-13 3:54 ` Lee Revell
2004-08-13 4:23 ` Lee Revell
2004-08-13 4:35 ` Roland Dreier
2004-08-13 4:41 ` Lee Revell
2004-08-13 4:46 ` Roland Dreier
2004-08-13 10:21 ` Ingo Molnar
2004-08-13 10:16 ` Ingo Molnar
2004-08-13 4:49 ` Matt Heler
2004-08-13 9:53 ` Peter Zijlstra
2004-08-13 10:19 ` Ingo Molnar
2004-08-13 10:23 ` Peter Zijlstra
2004-08-13 4:58 ` Lee Revell
2004-08-13 10:22 ` Ingo Molnar
2004-08-13 18:57 ` Lee Revell
2004-08-13 5:27 ` Lee Revell
2004-08-13 5:41 ` Lee Revell
2004-08-13 10:31 ` Ingo Molnar
2004-08-13 19:47 ` Lee Revell
2004-08-16 23:46 ` Lee Revell
2004-08-17 7:48 ` Ingo Molnar
2004-08-17 7:56 ` Lee Revell
2004-08-17 19:18 ` Theodore Ts'o
2004-08-19 10:54 ` Lee Revell
2004-08-19 11:19 ` Lee Revell
2004-08-19 19:30 ` Theodore Ts'o
2004-08-19 22:32 ` Lee Revell
2004-08-19 22:50 ` Lee Revell
2004-08-20 0:10 ` Lee Revell
2004-08-13 7:40 ` Lee Revell
2004-08-13 10:42 ` Florian Schmidt
2004-08-13 10:54 ` Ingo Molnar
2004-08-13 12:03 ` Florian Schmidt
2004-08-13 12:03 ` Ingo Molnar
[not found] ` <20040813145510.60e9e0f3@mango.fruits.de>
2004-08-14 8:57 ` Ingo Molnar
2004-08-14 11:28 ` James Courtier-Dutton
2004-08-14 11:51 ` Ingo Molnar
2004-08-14 12:19 ` James Courtier-Dutton
2004-08-14 12:32 ` Ingo Molnar
2004-08-14 16:52 ` James Courtier-Dutton
2004-08-19 9:10 ` Ingo Molnar
2004-08-19 9:07 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=411D9A2A.1000202@grupopie.com \
--to=pmarques@grupopie.com \
--cc=ak@muc.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.