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 \
struct _amd_data;
struct _amd_message
{
struct _amd_message *next;
struct _amd_message *prev;
stream_t stream; /* Associated file stream */
off_t body_start; /* Offset of body start in the message file */
off_t body_end; /* Offset of body end (size of file, effectively)*/
......@@ -72,8 +69,8 @@ struct _amd_data
/* List of messages: */
size_t msg_count; /* number of messages in the list */
struct _amd_message *msg_head; /* First */
struct _amd_message *msg_tail; /* Last */
size_t msg_max; /* maximum message buffer capacity */
struct _amd_message **msg_array;
unsigned long uidvalidity;
......@@ -92,9 +89,13 @@ struct _amd_data
int amd_init_mailbox __P((mailbox_t mailbox, size_t mhd_size,
struct _amd_data **pmhd));
void _amd_message_insert __P((struct _amd_data *mhd,
struct _amd_message *msg));
int _amd_message_insert __P((struct _amd_data *mhd,
struct _amd_message *msg));
int amd_message_stream_open __P((struct _amd_message *mhm));
void amd_message_stream_close __P((struct _amd_message *mhm));
void amd_cleanup (void *arg);
int amd_url_init (url_t url, const char *scheme);
struct _amd_message *_amd_get_message __P((struct _amd_data *amd,
size_t msgno));
int amd_msg_lookup __P((struct _amd_data *amd, struct _amd_message *msg,
size_t *pret));
......
......@@ -324,7 +324,8 @@ maildir_message_uid (message_t msg, size_t *puid)
static size_t
maildir_next_uid (struct _amd_data *amd)
{
struct _maildir_message *msg = (struct _maildir_message *) amd->msg_tail;
struct _maildir_message *msg = (struct _maildir_message *)
_amd_get_message (amd, amd->msg_count);
return (msg ? msg->uid : 0) + 1;
}
......@@ -489,13 +490,17 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name)
char *p = strchr (file_name, ':');
size_t length = p ? p - file_name : strlen (file_name);
int rc;
size_t i;
for (msg = (struct _maildir_message *) amd->msg_head;
msg
&& strlen (msg->file_name) >= length
&& (rc = memcmp (msg->file_name, file_name, length)) < 0;
msg = (struct _maildir_message *) msg->amd_message.next)
;
/*FIXME!*/
for (i = 0; i < amd->msg_count; i++)
{
msg = (struct _maildir_message *) amd->msg_array[i];
if (strlen (msg->file_name) <= length
&& (rc = memcmp (msg->file_name, file_name, length)) == 0)
break;
}
return rc == 0 ? msg : NULL;
}
......@@ -588,8 +593,8 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
if (do_notify)
{
struct _amd_message *mp;
for (mp = amd->msg_head; mp; mp = mp->next)
size_t i;
for (i = 0; i < amd->msg_count++; i++)
{
DISPATCH_ADD_MSG(mailbox, amd);
}
......@@ -609,11 +614,11 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
amd->uidvalidity = (unsigned long) time (NULL);
/* FIXME amd->uidnext = amd->msg_count + 1;*/
/* Tell that we have been modified for expunging. */
if (amd->msg_head)
if (amd->msg_count)
{
amd_message_stream_open (amd->msg_head);
amd_message_stream_close (amd->msg_head);
amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED;
amd_message_stream_open (amd->msg_array[0]);
amd_message_stream_close (amd->msg_array[0]);
amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
}
}
......
......@@ -85,7 +85,8 @@ mh_message_cmp (struct _amd_message *a, struct _amd_message *b)
static size_t
_mh_next_seq (struct _amd_data *amd)
{
struct _mh_message *msg = (struct _mh_message *) amd->msg_tail;
struct _mh_message *msg = (struct _mh_message *)
_amd_get_message (amd, amd->msg_count);
return (msg ? msg->seq_number : 0) + 1;
}
......@@ -111,16 +112,14 @@ _mh_message_name (struct _amd_message *amsg, int deleted)
static struct _mh_message *
_mh_get_message_seq (struct _amd_data *amd, size_t seq)
{
struct _mh_message *msg;
for (msg = (struct _mh_message *) amd->msg_head;
msg && msg->seq_number < seq;
msg = (struct _mh_message *) msg->amd_message.next)
;
struct _mh_message msg;
size_t index;
msg.seq_number = seq;
if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index))
return NULL;
if (msg)
return msg->seq_number == seq ? msg : NULL;
return NULL;
return (struct _mh_message *) _amd_get_message (amd, index);
}
/* Scan the mailbox */
......@@ -205,8 +204,9 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
if (do_notify)
{
struct _amd_message *mp;
for (mp = amd->msg_head; mp; mp = mp->next)
size_t i;
for (i = 0; i < amd->msg_count; i++)
{
DISPATCH_ADD_MSG(mailbox, amd);
}
......@@ -225,11 +225,11 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
{
amd->uidvalidity = (unsigned long)time (NULL);
/* Tell that we have been modified for expunging. */
if (amd->msg_head)
if (amd->msg_count)
{
amd_message_stream_open (amd->msg_head);
amd_message_stream_close (amd->msg_head);
amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED;
amd_message_stream_open (amd->msg_array[0]);
amd_message_stream_close (amd->msg_array[0]);
amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
}
}
......