Mercurial > dovecot > core-2.2
changeset 22130:39df47bebbe7
lib-index: Add cache to mail_cache_get_missing_reason()
This avoids excessive CPU usage when it's called in a loop for many mails.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 05 Jun 2017 21:53:18 +0300 |
parents | 5d18e2c27efe |
children | d1ad3d43a3d2 |
files | src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache-private.h |
diffstat | 2 files changed, 30 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-lookup.c Mon Jun 05 21:44:45 2017 +0300 +++ b/src/lib-index/mail-cache-lookup.c Mon Jun 05 21:53:18 2017 +0300 @@ -616,14 +616,31 @@ mail_cache_get_highest_seq_with_cache(struct mail_cache_view *view, uint32_t below_seq, uint32_t *reset_id_r) { - uint32_t seq; + struct mail_cache_missing_reason_cache *rc = &view->reason_cache; + uint32_t seq = below_seq-1, highest_checked_seq = 0; /* find the newest mail that has anything in cache */ - for (seq = below_seq-1; seq > 0; seq--) { - if (mail_cache_lookup_cur_offset(view->view, seq, reset_id_r) != 0) + if (rc->log_file_head_offset == view->view->log_file_head_offset && + rc->log_file_head_seq == view->view->log_file_head_seq) { + /* reason_cache matches the current view - we can use it */ + highest_checked_seq = rc->highest_checked_seq; + } else { + rc->log_file_head_offset = view->view->log_file_head_offset; + rc->log_file_head_seq = view->view->log_file_head_seq; + } + rc->highest_checked_seq = below_seq; + + /* first check anything not already in reason_cache */ + for (; seq > highest_checked_seq; seq--) { + if (mail_cache_lookup_cur_offset(view->view, seq, reset_id_r) != 0) { + rc->highest_seq_with_cache = seq; return seq; + } } - return 0; + if (seq == 0) + return 0; + /* then return the result from cache */ + return rc->highest_seq_with_cache; } const char *
--- a/src/lib-index/mail-cache-private.h Mon Jun 05 21:44:45 2017 +0300 +++ b/src/lib-index/mail-cache-private.h Mon Jun 05 21:53:18 2017 +0300 @@ -169,6 +169,14 @@ uoff_t size_sum; }; +struct mail_cache_missing_reason_cache { + uint32_t highest_checked_seq; + uint32_t highest_seq_with_cache; + + uint32_t log_file_head_seq; + uoff_t log_file_head_offset; +}; + struct mail_cache_view { struct mail_cache *cache; struct mail_index_view *view, *trans_view; @@ -177,6 +185,7 @@ uint32_t trans_seq1, trans_seq2; struct mail_cache_loop_track loop_track; + struct mail_cache_missing_reason_cache reason_cache; /* if cached_exists_buf[field] == cached_exists_value, it's cached. this allows us to avoid constantly clearing the whole buffer.