* [PATCH] fix f_version optimization for get_tgid_list
@ 2004-08-31 20:26 Manfred Spraul
2004-08-31 21:51 ` Roger Luethi
0 siblings, 1 reply; 2+ messages in thread
From: Manfred Spraul @ 2004-08-31 20:26 UTC (permalink / raw)
To: Linux Kernel Mailing List; +Cc: Andrew Morton, Ingo Molnar, Roger Luethi
[-- Attachment #1: Type: text/plain, Size: 919 bytes --]
Hi,
the kernel contains an optimization that skips the linked list walk in
get_tgid_list for the common case of sequential accesses.
Unfortunately the optimization is buggy (missing NULL pointer check for
the result of find_task_by_pid) and broken (actually - broken twice: the
tgid value that is stored in f_version is always 0 because tgid is
overwritten when the string is created and additionally the common case
is not filldir < 0, it's running out of nr_tgids).
The attached patch fixes these bugs.
Roger: could you run your 100k processes test against a kernel with this
fix applied? I'm just interested how much it helps. One obvious result
are fewer getdents64 syscalls: instead of returning 20 entries (480
bytes) the new code fills the user space buffer completely (42
entries/syscall).
Andrew, could you add the patch to your -mm tree?
Signed-Off-By: Manfred Spraul <manfred@colorfullife.com>
[-- Attachment #2: patch-tgid-bugfixes --]
[-- Type: text/plain, Size: 2172 bytes --]
--- 2.6/fs/proc/base.c 2004-08-20 19:59:19.000000000 +0200
+++ build-2.6/fs/proc/base.c 2004-08-31 21:42:28.000000000 +0200
@@ -1689,7 +1689,7 @@ static int get_tgid_list(int index, unsi
p = NULL;
if (version) {
p = find_task_by_pid(version);
- if (!thread_group_leader(p))
+ if (p && !thread_group_leader(p))
p = NULL;
}
@@ -1752,6 +1752,7 @@ int proc_pid_readdir(struct file * filp,
char buf[PROC_NUMBUF];
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
unsigned int nr_tgids, i;
+ int next_tgid;
if (!nr) {
ino_t ino = fake_ino(0,PROC_TGID_INO);
@@ -1761,26 +1762,45 @@ int proc_pid_readdir(struct file * filp,
nr++;
}
- /*
- * f_version caches the last tgid which was returned from readdir
+ /* f_version caches the tgid value that the last readdir call couldn't
+ * return. lseek aka telldir automagically resets f_version to 0.
*/
- nr_tgids = get_tgid_list(nr, filp->f_version, tgid_array);
-
- for (i = 0; i < nr_tgids; i++) {
- int tgid = tgid_array[i];
- ino_t ino = fake_ino(tgid,PROC_TGID_INO);
- unsigned long j = PROC_NUMBUF;
-
- do
- buf[--j] = '0' + (tgid % 10);
- while ((tgid /= 10) != 0);
-
- if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
- filp->f_version = tgid;
+ next_tgid = filp->f_version;
+ filp->f_version = 0;
+ for (;;) {
+ nr_tgids = get_tgid_list(nr, next_tgid, tgid_array);
+ if (!nr_tgids) {
+ /* no more entries ! */
break;
}
- filp->f_pos++;
+ next_tgid = 0;
+
+ /* do not use the last found pid, reserve it for next_tgid */
+ if (nr_tgids == PROC_MAXPIDS) {
+ nr_tgids--;
+ next_tgid = tgid_array[nr_tgids];
+ }
+
+ for (i=0;i<nr_tgids;i++) {
+ int tgid = tgid_array[i];
+ ino_t ino = fake_ino(tgid,PROC_TGID_INO);
+ unsigned long j = PROC_NUMBUF;
+
+ do
+ buf[--j] = '0' + (tgid % 10);
+ while ((tgid /= 10) != 0);
+
+ if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
+ /* returning this tgid failed, save it as the first
+ * pid for the next readir call */
+ filp->f_version = tgid_array[i];
+ goto out;
+ }
+ filp->f_pos++;
+ nr++;
+ }
}
+out:
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] fix f_version optimization for get_tgid_list
2004-08-31 20:26 [PATCH] fix f_version optimization for get_tgid_list Manfred Spraul
@ 2004-08-31 21:51 ` Roger Luethi
0 siblings, 0 replies; 2+ messages in thread
From: Roger Luethi @ 2004-08-31 21:51 UTC (permalink / raw)
To: Manfred Spraul; +Cc: Linux Kernel Mailing List, Andrew Morton, Ingo Molnar
test: top -d 0 -b -n 10 > /dev/null
==> 2.6.8 <==
real 0m19.092s
user 0m5.013s
sys 0m12.622s
CPU: CPU with timer interrupt, speed 0 MHz (estimated)
Profiling through timer interrupt
samples % image name symbol name
6338 35.9379 vmlinux get_tgid_list
1742 9.8775 vmlinux pid_alive
1264 7.1672 libc-2.3.3.so _IO_vfscanf_internal
940 5.3300 vmlinux number
625 3.5439 vmlinux proc_pid_stat
532 3.0166 libc-2.3.3.so _IO_vfprintf_internal
398 2.2567 vmlinux __d_lookup
297 1.6841 vmlinux vsnprintf
268 1.5196 vmlinux link_path_walk
266 1.5083 libc-2.3.3.so __i686.get_pc_thunk.bx
214 1.2134 libc-2.3.3.so ____strtoul_l_internal
210 1.1907 vmlinux task_statm
209 1.1851 libc-2.3.3.so _IO_default_xsputn_internal
199 1.1284 libc-2.3.3.so _IO_putc_internal
172 0.9753 libc-2.3.3.so ____strtol_l_internal
135 0.7655 libc-2.3.3.so _IO_sputbackc_internal
130 0.7371 libncurses.so.5.4 _nc_outch
124 0.7031 vmlinux pid_revalidate
115 0.6521 top task_show
112 0.6351 libc-2.3.3.so __find_specmb
103 0.5840 vmlinux atomic_dec_and_lock
98 0.5557 libc-2.3.3.so __funlockfile
76 0.4309 libncurses.so.5.4 tputs
73 0.4139 vmlinux system_call
72 0.4083 libc-2.3.3.so _IO_str_overflow_internal
72 0.4083 libc-2.3.3.so __GI___printf_fp
66 0.3742 vmlinux may_open
65 0.3686 libc-2.3.3.so __GI_strrchr
61 0.3459 vmlinux path_lookup
60 0.3402 libc-2.3.3.so __GI___errno_location
58 0.3289 libc-2.3.3.so __flockfile
55 0.3119 vmlinux __might_sleep
==> 2.6.8 + patch-tgid-bugfixes <==
real 0m10.062s
user 0m5.042s
sys 0m4.111s
CPU: CPU with timer interrupt, speed 0 MHz (estimated)
Profiling through timer interrupt
samples % image name symbol name
1330 14.5292 libc-2.3.3.so _IO_vfscanf_internal
931 10.1704 vmlinux number
618 6.7511 vmlinux proc_pid_stat
494 5.3965 libc-2.3.3.so _IO_vfprintf_internal
307 3.3537 vmlinux __d_lookup
296 3.2336 vmlinux vsnprintf
233 2.5453 libc-2.3.3.so _IO_putc_internal
216 2.3596 libc-2.3.3.so _IO_default_xsputn_internal
212 2.3159 libc-2.3.3.so ____strtoul_l_internal
208 2.2722 libc-2.3.3.so __i686.get_pc_thunk.bx
200 2.1848 libc-2.3.3.so ____strtol_l_internal
199 2.1739 vmlinux link_path_walk
198 2.1630 vmlinux task_statm
156 1.7042 libc-2.3.3.so _IO_sputbackc_internal
128 1.3983 libncurses.so.5.4 _nc_outch
122 1.3328 top task_show
110 1.2017 vmlinux pid_revalidate
84 0.9176 libc-2.3.3.so __funlockfile
81 0.8849 libc-2.3.3.so __find_specmb
72 0.7865 libncurses.so.5.4 tputs
68 0.7428 vmlinux system_call
65 0.7101 libc-2.3.3.so __GI___errno_location
64 0.6991 libc-2.3.3.so _IO_str_overflow_internal
63 0.6882 libc-2.3.3.so __flockfile
63 0.6882 vmlinux get_tgid_list
61 0.6664 libc-2.3.3.so __strnlen
59 0.6445 libc-2.3.3.so __GI___printf_fp
57 0.6227 vmlinux atomic_dec_and_lock
55 0.6008 libc-2.3.3.so __GI_strrchr
54 0.5899 vmlinux may_open
52 0.5681 libproc-3.2.3.so escape_str
51 0.5571 libc-2.3.3.so _IO_str_init_static_internal
51 0.5571 libc-2.3.3.so __GI___strtoul_internal
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-08-31 21:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-31 20:26 [PATCH] fix f_version optimization for get_tgid_list Manfred Spraul
2004-08-31 21:51 ` Roger Luethi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox