]> git.notmuchmail.org Git - notmuch/blob - test/corpus/cur/26:2,
Merge commit '0.6.1'
[notmuch] / test / corpus / cur / 26:2,
1 From: "Stewart Smith" <stewart@flamingspork.com>
2 To: notmuch@notmuchmail.org
3 Date: Wed, 18 Nov 2009 12:56:40 +1100
4 Subject: [notmuch] [PATCH 2/2] Read mail directory in inode number order
5 Message-ID: <1258509400-32511-1-git-send-email-stewart@flamingspork.com>
6
7 This gives a rather decent reduction in number of seeks required when
8 reading a Maildir that isn't in pagecache.
9
10 Most filesystems give some locality on disk based on inode numbers.
11 In ext[234] this is the inode tables, in XFS groups of sequential inode
12 numbers are together on disk and the most significant bits indicate
13 allocation group (i.e inode 1,000,000 is always after inode 1,000).
14
15 With this patch, we read in the whole directory, sort by inode number
16 before stat()ing the contents.
17
18 Ideally, directory is sequential and then we make one scan through the
19 file system stat()ing.
20
21 Since the universe is not ideal, we'll probably seek during reading the
22 directory and a fair bit while reading the inodes themselves.
23
24 However... with readahead, and stat()ing in inode order, we should be
25 in the best place possible to hit the cache.
26
27 In a (not very good) benchmark of "how long does it take to find the first
28 15,000 messages in my Maildir after 'echo 3 > /proc/sys/vm/drop_caches'",
29 this patch consistently cut at least 8 seconds off the scan time.
30
31 Without patch: 50 seconds
32 With patch: 38-42 seconds.
33
34 (I did this in a previous maildir reading project and saw large improvements too)
35 ---
36  notmuch-new.c |   32 +++++++++++++++-----------------
37  1 files changed, 15 insertions(+), 17 deletions(-)
38
39 diff --git a/notmuch-new.c b/notmuch-new.c
40 index 83a05ba..11fad8c 100644
41 --- a/notmuch-new.c
42 +++ b/notmuch-new.c
43 @@ -73,6 +73,11 @@ add_files_print_progress (add_files_state_t *state)
44      fflush (stdout);
45  }
46  
47 +static int ino_cmp(const struct dirent **a, const struct dirent **b)
48 +{
49 +  return ((*a)->d_ino < (*b)->d_ino)? -1: 1;
50 +}
51 +
52  /* Examine 'path' recursively as follows:
53   *
54   *   o Ask the filesystem for the mtime of 'path' (path_mtime)
55 @@ -100,13 +105,12 @@ add_files_recursive (notmuch_database_t *notmuch,
56                      add_files_state_t *state)
57  {
58      DIR *dir = NULL;
59 -    struct dirent *e, *entry = NULL;
60 -    int entry_length;
61 -    int err;
62 +    struct dirent *entry = NULL;
63      char *next = NULL;
64      time_t path_mtime, path_dbtime;
65      notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;
66      notmuch_message_t *message = NULL;
67 +    struct dirent **namelist = NULL;
68  
69      /* If we're told to, we bail out on encountering a read-only
70       * directory, (with this being a clear clue from the user to
71 @@ -122,31 +126,23 @@ add_files_recursive (notmuch_database_t *notmuch,
72      path_mtime = st->st_mtime;
73  
74      path_dbtime = notmuch_database_get_timestamp (notmuch, path);
75 +    int n_entries= scandir(path, &namelist, 0, ino_cmp);
76  
77 -    dir = opendir (path);
78 -    if (dir == NULL) {
79 +    if (n_entries == -1) {
80         fprintf (stderr, "Error opening directory %s: %s\n",
81                  path, strerror (errno));
82         ret = NOTMUCH_STATUS_FILE_ERROR;
83         goto DONE;
84      }
85  
86 -    entry_length = offsetof (struct dirent, d_name) +
87 -       pathconf (path, _PC_NAME_MAX) + 1;
88 -    entry = malloc (entry_length);
89 +    int i=0;
90  
91      while (!interrupted) {
92 -       err = readdir_r (dir, entry, &e);
93 -       if (err) {
94 -           fprintf (stderr, "Error reading directory: %s\n",
95 -                    strerror (errno));
96 -           ret = NOTMUCH_STATUS_FILE_ERROR;
97 -           goto DONE;
98 -       }
99 -
100 -       if (e == NULL)
101 +       if (i == n_entries)
102             break;
103  
104 +        entry= namelist[i++];
105 +
106         /* If this directory hasn't been modified since the last
107          * add_files, then we only need to look further for
108          * sub-directories. */
109 @@ -243,6 +239,8 @@ add_files_recursive (notmuch_database_t *notmuch,
110         free (entry);
111      if (dir)
112         closedir (dir);
113 +    if (namelist)
114 +       free (namelist);
115  
116      return ret;
117  }
118 -- 
119 1.6.3.3
120
121