From: Timo Sirainen Date: Mon, 5 Jun 2017 18:53:18 +0000 (+0300) Subject: lib-index: Add cache to mail_cache_get_missing_reason() X-Git-Tag: 2.2.31.rc1~129 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=29e2a26bd3a85ce7d28c81142db184ee2aa860ea;p=thirdparty%2Fdovecot%2Fcore.git 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. --- diff --git a/src/lib-index/mail-cache-lookup.c b/src/lib-index/mail-cache-lookup.c index 31b20e36fd..f1490212fe 100644 --- a/src/lib-index/mail-cache-lookup.c +++ b/src/lib-index/mail-cache-lookup.c @@ -616,14 +616,31 @@ static uint32_t 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 * diff --git a/src/lib-index/mail-cache-private.h b/src/lib-index/mail-cache-private.h index 1fb8b3ad6c..ff748cca31 100644 --- a/src/lib-index/mail-cache-private.h +++ b/src/lib-index/mail-cache-private.h @@ -169,6 +169,14 @@ struct mail_cache_loop_track { 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 @@ struct mail_cache_view { 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.