Ingo Molnar wrote: >On Sun, 16 Mar 2003, Manfred Spraul wrote: > > > >>Below is a proposal to get rid of the quadratic behaviour of >>proc_pid_readir(): Instead of storing the task number in f_pos and >>walking tasks by tasklist order, the pid is stored in f_pos and the >>tasks are walked by (hash-mangled) pid order. >> >> > >have you seen my "procfs/procps threading performance speedup" patch? It >does something like this. > > The implementation is flawed: >+static int get_pid_list(int index, int *pids, struct file *filp) > { >- struct task_struct *p; >- int nr_pids = 0; >+ int nr_pids = 0, pid = 0, pid_cursor = (int)filp->private_data; >+ struct task_struct *g = NULL, *p = NULL; > >- index--; > read_lock(&tasklist_lock); >- for_each_process(p) { >- int pid = p->pid; >- if (!pid) >- continue; >+ if (pid_cursor) { >+ p = find_task_by_pid(pid_cursor); >+ g = p->group_leader; >+ } >+ if (!p) { >+ g = p = &init_task; >+ index--; >+ } else >+ index = 0; >+ >+ goto inside; >+ >+ __do_each_thread(g, p) { > if (--index >= 0) > continue; >- pids[nr_pids] = pid; >+ pid = p->pid; >+ if (!pid) >+ BUG(); >+ if (p->tgid != p->pid) >+ pids[nr_pids] = -pid; >+ else >+ pids[nr_pids] = pid; > nr_pids++; > if (nr_pids >= PROC_MAXPIDS) >- break; >- } >+ goto out; >+inside: >+ ; >+ } while_each_thread(g, p); >+out: >+ filp->private_data = (void *)pid; > read_unlock(&tasklist_lock); >+ > return nr_pids; > } > > get_pid_list stores up to 20 pids in an array, and the last pid in the array is stored in filp->private_data, for the next call. > int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) > { >- unsigned int pid_array[PROC_MAXPIDS]; >+ int pid_array[PROC_MAXPIDS]; > char buf[PROC_NUMBUF]; > unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; > unsigned int nr_pids, i; >@@ -1192,14 +1217,16 @@ int proc_pid_readdir(struct file * filp, > nr++; > } > >- nr_pids = get_pid_list(nr, pid_array); >+ nr_pids = get_pid_list(nr, pid_array, filp); > > for (i = 0; i < nr_pids; i++) { >- int pid = pid_array[i]; >+ int pid = abs(pid_array[i]); > ino_t ino = fake_ino(pid,PROC_PID_INO); > unsigned long j = PROC_NUMBUF; > > do buf[--j] = '0' + (pid % 10); while (pid/=10); >+ if (pid_array[i] < 0) >+ buf[--j] = '.'; > > if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) > break; > > But: proc_pid_readdir() doesn't use all 20 pids: It may return early if the user space buffer is full. Then your patch skips a few threads. Attached is my test app: ./getdents /proc 0 24 returns just 3 threads, ./getdents /proc 0 4000 returns (probably) all: 66 threads or processes. -- Manfred