Here's a simple program to trigger the issue with /proc/<pid>/maps. Thanks, Calvin
/* Simple program to reproduce O(N^2) behavior reading /proc/<pid>/maps * * Example on a random server: * * $ ./map_repro 0 * Spawning 0 threads * Reading /proc/self/maps... read 2189 bytes in 1 syscalls in 33us! * $ ./map_repro 10 * Spawning 10 threads * Reading /proc/self/maps... read 3539 bytes in 1 syscalls in 55us! * $ ./map_repro 100 * Spawning 100 threads * Reading /proc/self/maps... read 15689 bytes in 4 syscalls in 373us! * $ ./map_repro 1000 * Spawning 1000 threads * Reading /proc/self/maps... read 137189 bytes in 34 syscalls in 32376us! * $ ./map_repro 2000 * Spawning 2000 threads * Reading /proc/self/maps... read 272189 bytes in 68 syscalls in 119980us! * $ ./map_repro 4000 * Spawning 4000 threads * Reading /proc/self/maps... read 544912 bytes in 134 syscalls in 712200us! * $ ./map_repro 8000 * Spawning 8000 threads * Reading /proc/self/maps... read 1090189 bytes in 268 syscalls in 3650718us! * $ ./map_repro 16000 * Spawning 16000 threads * Reading /proc/self/maps... read 2178189 bytes in 534 syscalls in 42701311us! */ #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <limits.h> #include <pthread.h> #include <unistd.h> #include <time.h> #include <fcntl.h> static char buf[65536] = {0}; static void time_maps_read(void) { struct timespec then, now; long usec_elapsed; int ret, fd; int count = 0; int rd = 0; fd = open("/proc/self/maps", O_RDONLY); if (fd == -1) { printf("Couldn't open /proc/self/maps, bailing...\n"); return; } printf("Reading /proc/self/maps... "); ret = clock_gettime(CLOCK_MONOTONIC, &then); while (1) { ret = read(fd, &buf, 65536); if (!ret || ret == -1) break; rd += ret; count++; } ret = clock_gettime(CLOCK_MONOTONIC, &now); usec_elapsed = (now.tv_sec - then.tv_sec) * 1000000L; usec_elapsed += (now.tv_nsec - then.tv_nsec) / 1000L; printf("read %d bytes in %d syscalls in %ldus!\n", rd, count, usec_elapsed); close(fd); } static void *do_nothing_forever(void *unused) { while (1) sleep(60); return NULL; } int main(int args, char **argv) { int i, ret, threads_to_spawn = 0; pthread_t tmp; if (args != 1) { threads_to_spawn = atoi(argv[1]); printf("Spawning %d threads\n", threads_to_spawn); } for (i = 0; i < threads_to_spawn; i++) { ret = pthread_create(&tmp, NULL, do_nothing_forever, NULL); if (ret) printf("Thread %d failed to spawn?\n", i); } time_maps_read(); return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/