Use sorted message array with binary
searches/inserts. This speeds up the mh/maildir operations considerably. Testing on a MH folder with 6000 messages shows the following data: Time of execution List Array+Bsearch % Speedup (times) scan 24.795 7.526 30.3 3.294 refile (to) 10.915 0.068 0.6 160.514 rmm 10.893 0.105 1 103.742
Showing
4 changed files
with
42 additions
and
36 deletions
This diff is collapsed.
Click to expand it.
... | @@ -39,9 +39,6 @@ do \ | ... | @@ -39,9 +39,6 @@ do \ |
39 | struct _amd_data; | 39 | struct _amd_data; |
40 | struct _amd_message | 40 | struct _amd_message |
41 | { | 41 | { |
42 | struct _amd_message *next; | ||
43 | struct _amd_message *prev; | ||
44 | |||
45 | stream_t stream; /* Associated file stream */ | 42 | stream_t stream; /* Associated file stream */ |
46 | off_t body_start; /* Offset of body start in the message file */ | 43 | off_t body_start; /* Offset of body start in the message file */ |
47 | off_t body_end; /* Offset of body end (size of file, effectively)*/ | 44 | off_t body_end; /* Offset of body end (size of file, effectively)*/ |
... | @@ -72,8 +69,8 @@ struct _amd_data | ... | @@ -72,8 +69,8 @@ struct _amd_data |
72 | 69 | ||
73 | /* List of messages: */ | 70 | /* List of messages: */ |
74 | size_t msg_count; /* number of messages in the list */ | 71 | size_t msg_count; /* number of messages in the list */ |
75 | struct _amd_message *msg_head; /* First */ | 72 | size_t msg_max; /* maximum message buffer capacity */ |
76 | struct _amd_message *msg_tail; /* Last */ | 73 | struct _amd_message **msg_array; |
77 | 74 | ||
78 | unsigned long uidvalidity; | 75 | unsigned long uidvalidity; |
79 | 76 | ||
... | @@ -92,9 +89,13 @@ struct _amd_data | ... | @@ -92,9 +89,13 @@ struct _amd_data |
92 | 89 | ||
93 | int amd_init_mailbox __P((mailbox_t mailbox, size_t mhd_size, | 90 | int amd_init_mailbox __P((mailbox_t mailbox, size_t mhd_size, |
94 | struct _amd_data **pmhd)); | 91 | struct _amd_data **pmhd)); |
95 | void _amd_message_insert __P((struct _amd_data *mhd, | 92 | int _amd_message_insert __P((struct _amd_data *mhd, |
96 | struct _amd_message *msg)); | 93 | struct _amd_message *msg)); |
97 | int amd_message_stream_open __P((struct _amd_message *mhm)); | 94 | int amd_message_stream_open __P((struct _amd_message *mhm)); |
98 | void amd_message_stream_close __P((struct _amd_message *mhm)); | 95 | void amd_message_stream_close __P((struct _amd_message *mhm)); |
99 | void amd_cleanup (void *arg); | 96 | void amd_cleanup (void *arg); |
100 | int amd_url_init (url_t url, const char *scheme); | 97 | int amd_url_init (url_t url, const char *scheme); |
98 | struct _amd_message *_amd_get_message __P((struct _amd_data *amd, | ||
99 | size_t msgno)); | ||
100 | int amd_msg_lookup __P((struct _amd_data *amd, struct _amd_message *msg, | ||
101 | size_t *pret)); | ... | ... |
... | @@ -324,7 +324,8 @@ maildir_message_uid (message_t msg, size_t *puid) | ... | @@ -324,7 +324,8 @@ maildir_message_uid (message_t msg, size_t *puid) |
324 | static size_t | 324 | static size_t |
325 | maildir_next_uid (struct _amd_data *amd) | 325 | maildir_next_uid (struct _amd_data *amd) |
326 | { | 326 | { |
327 | struct _maildir_message *msg = (struct _maildir_message *) amd->msg_tail; | 327 | struct _maildir_message *msg = (struct _maildir_message *) |
328 | _amd_get_message (amd, amd->msg_count); | ||
328 | return (msg ? msg->uid : 0) + 1; | 329 | return (msg ? msg->uid : 0) + 1; |
329 | } | 330 | } |
330 | 331 | ||
... | @@ -489,13 +490,17 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name) | ... | @@ -489,13 +490,17 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name) |
489 | char *p = strchr (file_name, ':'); | 490 | char *p = strchr (file_name, ':'); |
490 | size_t length = p ? p - file_name : strlen (file_name); | 491 | size_t length = p ? p - file_name : strlen (file_name); |
491 | int rc; | 492 | int rc; |
493 | size_t i; | ||
492 | 494 | ||
493 | for (msg = (struct _maildir_message *) amd->msg_head; | 495 | /*FIXME!*/ |
494 | msg | 496 | for (i = 0; i < amd->msg_count; i++) |
495 | && strlen (msg->file_name) >= length | 497 | { |
496 | && (rc = memcmp (msg->file_name, file_name, length)) < 0; | 498 | msg = (struct _maildir_message *) amd->msg_array[i]; |
497 | msg = (struct _maildir_message *) msg->amd_message.next) | 499 | |
498 | ; | 500 | if (strlen (msg->file_name) <= length |
501 | && (rc = memcmp (msg->file_name, file_name, length)) == 0) | ||
502 | break; | ||
503 | } | ||
499 | return rc == 0 ? msg : NULL; | 504 | return rc == 0 ? msg : NULL; |
500 | } | 505 | } |
501 | 506 | ||
... | @@ -588,8 +593,8 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, | ... | @@ -588,8 +593,8 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, |
588 | 593 | ||
589 | if (do_notify) | 594 | if (do_notify) |
590 | { | 595 | { |
591 | struct _amd_message *mp; | 596 | size_t i; |
592 | for (mp = amd->msg_head; mp; mp = mp->next) | 597 | for (i = 0; i < amd->msg_count++; i++) |
593 | { | 598 | { |
594 | DISPATCH_ADD_MSG(mailbox, amd); | 599 | DISPATCH_ADD_MSG(mailbox, amd); |
595 | } | 600 | } |
... | @@ -609,11 +614,11 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, | ... | @@ -609,11 +614,11 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, |
609 | amd->uidvalidity = (unsigned long) time (NULL); | 614 | amd->uidvalidity = (unsigned long) time (NULL); |
610 | /* FIXME amd->uidnext = amd->msg_count + 1;*/ | 615 | /* FIXME amd->uidnext = amd->msg_count + 1;*/ |
611 | /* Tell that we have been modified for expunging. */ | 616 | /* Tell that we have been modified for expunging. */ |
612 | if (amd->msg_head) | 617 | if (amd->msg_count) |
613 | { | 618 | { |
614 | amd_message_stream_open (amd->msg_head); | 619 | amd_message_stream_open (amd->msg_array[0]); |
615 | amd_message_stream_close (amd->msg_head); | 620 | amd_message_stream_close (amd->msg_array[0]); |
616 | amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED; | 621 | amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; |
617 | } | 622 | } |
618 | } | 623 | } |
619 | } | 624 | } | ... | ... |
... | @@ -85,7 +85,8 @@ mh_message_cmp (struct _amd_message *a, struct _amd_message *b) | ... | @@ -85,7 +85,8 @@ mh_message_cmp (struct _amd_message *a, struct _amd_message *b) |
85 | static size_t | 85 | static size_t |
86 | _mh_next_seq (struct _amd_data *amd) | 86 | _mh_next_seq (struct _amd_data *amd) |
87 | { | 87 | { |
88 | struct _mh_message *msg = (struct _mh_message *) amd->msg_tail; | 88 | struct _mh_message *msg = (struct _mh_message *) |
89 | _amd_get_message (amd, amd->msg_count); | ||
89 | return (msg ? msg->seq_number : 0) + 1; | 90 | return (msg ? msg->seq_number : 0) + 1; |
90 | } | 91 | } |
91 | 92 | ||
... | @@ -111,16 +112,14 @@ _mh_message_name (struct _amd_message *amsg, int deleted) | ... | @@ -111,16 +112,14 @@ _mh_message_name (struct _amd_message *amsg, int deleted) |
111 | static struct _mh_message * | 112 | static struct _mh_message * |
112 | _mh_get_message_seq (struct _amd_data *amd, size_t seq) | 113 | _mh_get_message_seq (struct _amd_data *amd, size_t seq) |
113 | { | 114 | { |
114 | struct _mh_message *msg; | 115 | struct _mh_message msg; |
115 | 116 | size_t index; | |
116 | for (msg = (struct _mh_message *) amd->msg_head; | 117 | |
117 | msg && msg->seq_number < seq; | 118 | msg.seq_number = seq; |
118 | msg = (struct _mh_message *) msg->amd_message.next) | 119 | if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index)) |
119 | ; | 120 | return NULL; |
120 | 121 | ||
121 | if (msg) | 122 | return (struct _mh_message *) _amd_get_message (amd, index); |
122 | return msg->seq_number == seq ? msg : NULL; | ||
123 | return NULL; | ||
124 | } | 123 | } |
125 | 124 | ||
126 | /* Scan the mailbox */ | 125 | /* Scan the mailbox */ |
... | @@ -205,8 +204,9 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, | ... | @@ -205,8 +204,9 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, |
205 | 204 | ||
206 | if (do_notify) | 205 | if (do_notify) |
207 | { | 206 | { |
208 | struct _amd_message *mp; | 207 | size_t i; |
209 | for (mp = amd->msg_head; mp; mp = mp->next) | 208 | |
209 | for (i = 0; i < amd->msg_count; i++) | ||
210 | { | 210 | { |
211 | DISPATCH_ADD_MSG(mailbox, amd); | 211 | DISPATCH_ADD_MSG(mailbox, amd); |
212 | } | 212 | } |
... | @@ -225,11 +225,11 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, | ... | @@ -225,11 +225,11 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, |
225 | { | 225 | { |
226 | amd->uidvalidity = (unsigned long)time (NULL); | 226 | amd->uidvalidity = (unsigned long)time (NULL); |
227 | /* Tell that we have been modified for expunging. */ | 227 | /* Tell that we have been modified for expunging. */ |
228 | if (amd->msg_head) | 228 | if (amd->msg_count) |
229 | { | 229 | { |
230 | amd_message_stream_open (amd->msg_head); | 230 | amd_message_stream_open (amd->msg_array[0]); |
231 | amd_message_stream_close (amd->msg_head); | 231 | amd_message_stream_close (amd->msg_array[0]); |
232 | amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED; | 232 | amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; |
233 | } | 233 | } |
234 | } | 234 | } |
235 | } | 235 | } | ... | ... |
-
Please register or sign in to post a comment