This should make aerc a bit more responsive when opening large maildir folders. Robin Jarry (2): dirlist: use shorter delay before listing directory contents maildir: defer the count of recent messages config/aerc.conf.in | 7 +++++ config/config.go | 2 ++ doc/aerc-config.5.scd | 8 ++++++ widgets/dirlist.go | 2 +- worker/maildir/worker.go | 56 ++++++++++++++++++++++------------------ 5 files changed, 49 insertions(+), 26 deletions(-) -- 2.30.2
aerc/patches: SUCCESS in 3m50s [maildir: speed improvements][0] from [Robin Jarry][1] [0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/28814 [1]: mailto:robin@jarry.cc ✓ #682821 SUCCESS aerc/patches/debian-stable.yml https://builds.sr.ht/~rjarry/job/682821 ✓ #682822 SUCCESS aerc/patches/fedora-latest.yml https://builds.sr.ht/~rjarry/job/682822 ✓ #682820 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/682820 ✓ #682823 SUCCESS aerc/patches/openbsd.yml https://builds.sr.ht/~rjarry/job/682823
Hi Robin On Fri Jan 28, 2022 at 2:11 PM CET, Robin Jarry wrote:
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~rjarry/aerc-devel/patches/28814/mbox | git am -3Learn more about email & git
1 second is a bit excessive. Use 200ms which should cover most quick folder changes. Add an option to make that delay configurable by the users. References: https://todo.sr.ht/~rjarry/aerc/16 Fixes: cb3090956cfd ("dirlist: skip unnecessary change-folder action") Suggested-by: Koni Marti <koni.marti@gmail.com> Signed-off-by: Robin Jarry <robin@jarry.cc> --- config/aerc.conf.in | 7 +++++++ config/config.go | 2 ++ doc/aerc-config.5.scd | 8 ++++++++ widgets/dirlist.go | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/config/aerc.conf.in b/config/aerc.conf.in index 3919b396753a..9f45883f51a5 100644 --- a/config/aerc.conf.in +++ b/config/aerc.conf.in @@ -74,6 +74,13 @@ pinned-tab-marker='`' # Default: %n %>r dirlist-format=%n %>r +# Delay after which the messages are actually listed when entering a directory. +# This avoids loading messages when skipping over folders and makes the UI more +# responsive. If you do not want that, set it to 0s. +# +# Default: 200ms +dirlist-delay=200ms + # List of space-separated criteria to sort the messages by, see *sort* # command in *aerc*(1) for reference. Prefixing a criterion with "-r " # reverses that criterion. diff --git a/config/config.go b/config/config.go index 374fd5c70156..e2acbaf38672 100644 --- a/config/config.go +++ b/config/config.go @@ -47,6 +47,7 @@ type UIConfig struct { Spinner string `ini:"spinner"` SpinnerDelimiter string `ini:"spinner-delimiter"` DirListFormat string `ini:"dirlist-format"` + DirListDelay time.Duration `ini:"dirlist-delay"` Sort []string `delim:" "` NextMessageOnDelete bool `ini:"next-message-on-delete"` CompletionDelay time.Duration `ini:"completion-delay"` @@ -564,6 +565,7 @@ func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*Aer Spinner: "[..] , [..] , [..] , [..] , [..], [..] , [..] , [..] ", SpinnerDelimiter: ",", DirListFormat: "%n %>r", + DirListDelay: 200 * time.Millisecond, NextMessageOnDelete: true, CompletionDelay: 250 * time.Millisecond, CompletionPopovers: true, diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 89485b27afe6..f40c9cb09c38 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -177,6 +177,14 @@ These options are configured in the *[ui]* section of aerc.conf. | %>X : make format specifier 'X' be right justified +*dirlist-delay* + Delay after which the messages are actually listed when entering + a directory. This avoids loading messages when skipping over folders + and makes the UI more responsive. If you do not want that, set it to + 0s. + + Default: 200ms + *next-message-on-delete* Moves to next message when the current message is deleted diff --git a/widgets/dirlist.go b/widgets/dirlist.go index 53afc1dd83c5..6f8869d57411 100644 --- a/widgets/dirlist.go +++ b/widgets/dirlist.go @@ -96,7 +96,7 @@ func (dirlist *DirectoryList) Select(name string) { go func() { select { - case <-time.After(1 * time.Second): + case <-time.After(dirlist.aercConf.Ui.DirListDelay): dirlist.worker.PostAction(&types.OpenDirectory{Directory: name}, func(msg types.WorkerMessage) { switch msg.(type) { -- 2.30.2
Since commit 01c96e78dfe8 ("Update DirectoryInfo handling for maildir"), flags are checked for every message of a folder when entering it. Iterating over all messages of a folder takes a long time for large collections of emails. Only count the number of messages and state that the directory info counts are not accurate. Defer the parsing of message flags in a goroutine to have a more responsive UI.
Thanks! When I test it on a maildir with 400,000 messages, I get a speed improvement of ~3x in the startup time until the message list has loaded.
Fixes: https://todo.sr.ht/~rjarry/aerc/16 Suggested-by: Koni Marti <koni.marti@gmail.com> Signed-off-by: Robin Jarry <robin@jarry.cc> --- I'm not sure if there is a risk of nil pointer dereference when accessing the dirinfo object after returning from getDirectoryInfo(). My tests did not reveal any problem but there may be a race somewhere.
Didn't run into any problems during testing either.
worker/maildir/worker.go | 56 ++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 2f75f12ae5e0..c347de9832fe 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -132,7 +132,7 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo { // total unread Unseen: 0, - AccurateCounts: true, + AccurateCounts: false, } dir := w.c.Dir(name) @@ -143,32 +143,38 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo { return dirInfo } - for _, uid := range uids { - message, err := w.c.Message(dir, uid) - if err != nil { - w.worker.Logger.Printf("could not get message: %v", err) - continue - } - flags, err := message.Flags() - if err != nil { - w.worker.Logger.Printf("could not get flags: %v", err) - continue - } - seen := false - for _, flag := range flags { - if flag == maildir.FlagSeen { - seen = true + dirInfo.Exists = len(uids) + + go func() { + for _, uid := range uids { + message, err := w.c.Message(dir, uid) + if err != nil { + w.worker.Logger.Printf("could not get message: %v", err) + continue + } + flags, err := message.Flags() + if err != nil { + w.worker.Logger.Printf("could not get flags: %v", err) + continue + } + seen := false + for _, flag := range flags { + if flag == maildir.FlagSeen { + seen = true + } + } + if !seen { + dirInfo.Unseen++ + } + if w.c.IsRecent(uid) { + dirInfo.Recent++ } } - if !seen { - dirInfo.Unseen++ - } - if w.c.IsRecent(uid) { - dirInfo.Recent++ - } - } - dirInfo.Unseen += dirInfo.Recent - dirInfo.Exists = len(uids) + dirInfo.Recent + dirInfo.Unseen += dirInfo.Recent + dirInfo.Exists += dirInfo.Recent + dirInfo.AccurateCounts = true + }() + return dirInfo } -- 2.30.2
builds.sr.ht <builds@sr.ht>aerc/patches: SUCCESS in 3m50s [maildir: speed improvements][0] from [Robin Jarry][1] [0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/28814 [1]: mailto:robin@jarry.cc ✓ #682821 SUCCESS aerc/patches/debian-stable.yml https://builds.sr.ht/~rjarry/job/682821 ✓ #682822 SUCCESS aerc/patches/fedora-latest.yml https://builds.sr.ht/~rjarry/job/682822 ✓ #682820 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/682820 ✓ #682823 SUCCESS aerc/patches/openbsd.yml https://builds.sr.ht/~rjarry/job/682823
Hi Robin On Fri Jan 28, 2022 at 2:11 PM CET, Robin Jarry wrote: