Commit 84c33414 84c334143ef6fbe6220e3d889c32375f63c8e8e2 by Sergey Poznyakoff

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
1 parent 801152df
...@@ -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 }
......