#include #include #include #include #include #include #include #include #include #include #include struct dirent_s { unsigned long long d_ino; long long d_off; unsigned short int d_reclen; unsigned char d_type; char *d_name; }; static void disaster (const char *what) { fprintf (stderr, "%s failed: %s\n", what, strerror (errno)); exit (1); } static void dump_caches (void) { int fd = open ("/proc/sys/vm/drop_caches", O_RDWR); if (fd < 0) disaster ("opening drop_caches"); if (write (fd, "3", strlen ("3")) < 0) disaster ("writing drop_caches"); if (close (fd) < 0) disaster ("closing drop_caches"); } static int ino_cmp(const void *a, const void *b) { const struct dirent_s *ds_a = (const struct dirent_s *) a; const struct dirent_s *ds_b = (const struct dirent_s *) b; unsigned int i_a, i_b; i_a = ds_a->d_ino; i_b = ds_b->d_ino; return (i_a - i_b); } static double tv_to_sec (const struct timeval *tv) { return tv->tv_sec + tv->tv_usec / 1000000.0; } static double time_diff (const struct timeval *before, const struct timeval *after) { return tv_to_sec (after) - tv_to_sec (before); } static int pot (int n) { int p = 1; while (p <= n) p *= 2; return p; } int main (int argc, char **argv) { DIR *dir = opendir ("."); struct dirent *ent; struct timeval before; struct timeval after; struct dirent_s *ds = NULL; int n_files; int do_sort = 0; int drop_caches = 1; int i, c; while ((c = getopt (argc, argv, "sc")) != EOF) { switch (c) { case 's': do_sort++; break; case 'c': drop_caches = 0; break; default: printf("Usage: %s [-s]\n", argv[0]); } } /* Dump caches */ if (drop_caches) dump_caches(); sleep (1); /* Read directory */ errno = 0; gettimeofday (&before, NULL); n_files = 0; while ((ent = readdir (dir))) { ds = realloc (ds, sizeof (struct dirent_s) * pot (n_files)); if (!ds) disaster ("realloc"); ds[n_files].d_name = strdup (ent->d_name); ds[n_files].d_ino = ent->d_ino; n_files++; } if (errno != 0) disaster ("readdir"); gettimeofday (&after, NULL); printf ("Time to readdir(): %f s\n", time_diff (&before, &after)); if (do_sort) qsort(ds, n_files, sizeof(struct dirent_s), ino_cmp); /* Stat all the files */ gettimeofday (&before, NULL); for (i = 0; i < n_files; ++i) { struct stat statbuf; stat (ds[i].d_name, &statbuf); } gettimeofday (&after, NULL); printf ("Time to stat %d files: %f s\n", n_files, time_diff (&before, &after)); return 0; }