Skip to content

Computing total_messages isn't cheap but done on every keypress #1716

Description

@dominikh

Describe the bug

My notmuch database contains almost 2 million messages. Any alot buffer with a status bar, such as a thread, is unusably slow, with any keypress lagging noticeably.

According to perf, 88% of time is spent in _notmuch_query_count_documents. Applying the following hack removes this source of slowness:

diff --git i/alot/ui.py w/alot/ui.py
index 4c44809a..311ff4bf 100644
--- i/alot/ui.py
+++ w/alot/ui.py
@@ -677,7 +677,7 @@ class UI:
             btype = cb.modename
             info['buffer_no'] = self.buffers.index(cb)
             info['buffer_type'] = btype
-        info['total_messages'] = self.dbman.count_messages('*')
+        # info['total_messages'] = self.dbman.count_messages('*')
         info['pending_writes'] = len(self.dbman.writequeue)
         info['input_queue'] = ' '.join(self.input_queue)

Unfortunately, just removing total_messages from all statusbar settings isn't sufficient, because the information gets calculated unconditionally.

I believe that count_messages runs in O(n) time and has to iterate over the result set and can't trivially retrieve the count.

Another way of reproducing it is with notmuch count "*", which finishes in 270ms on my good system and in 1s on my weak system, obviously not something you want to run on every keypress.

Software Versions

  • Python version: 3.12.10
  • Notmuch version: 0.40
  • Alot version: 40c57d6, also present in v0.11

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions