diff options
author | Tim Culverhouse <tim@timculverhouse.com> | 2022-07-03 10:11:13 -0500 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-07-03 21:32:24 +0200 |
commit | 4240f1fbfd095724bcbb0ea49cfa561c973ba6ce (patch) | |
tree | dbece5561d81a56eb106d0f6fe2019fb6d41e9c9 | |
parent | d45c07eb6a0955a24efec7bd915ba19746042778 (diff) | |
download | aerc-4240f1fbfd095724bcbb0ea49cfa561c973ba6ce.zip |
perf: reduce calls to GetUiConfig
GetUiConfig was being called many times, and came up as a high CPU user
in a cpuprofile. Every call would merge a UIConfig, which is a costly
operation. Ideally, we would only need to have a config for every
account X every directory. We also have a context for subjects. This
patch stores all FOLDER and ACCOUNT level configs and reuses those
merged objects. The SUBJECT contexts are not stored in favor of merging
on-the-go, with a TODO comment to deprecate that feature and implement a
better per-message styling option. I suspect this feature is not used
very much.
Before applying this patch with my setup, GetUiConfig is called 1159
times just to open aerc. After applying, this is reduced to 37.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r-- | config/config.go | 4 | ||||
-rw-r--r-- | widgets/account.go | 10 | ||||
-rw-r--r-- | widgets/dirlist.go | 13 | ||||
-rw-r--r-- | widgets/msglist.go | 23 |
4 files changed, 36 insertions, 14 deletions
diff --git a/config/config.go b/config/config.go index ee8dc6a..8a243c3 100644 --- a/config/config.go +++ b/config/config.go @@ -1027,6 +1027,10 @@ func (config AercConfig) GetUiConfig(params map[ContextType]string) *UIConfig { return &baseUi } +func (config *AercConfig) GetContextualUIConfigs() []UIConfigContext { + return config.ContextualUis +} + func (uiConfig UIConfig) GetStyle(so StyleObject) tcell.Style { return uiConfig.style.Get(so) } diff --git a/widgets/account.go b/widgets/account.go index 725090e..55e76be 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -34,17 +34,14 @@ type AccountView struct { worker *types.Worker state *statusline.State newConn bool // True if this is a first run after a new connection/reconnection + uiConf *config.UIConfig } func (acct *AccountView) UiConfig() *config.UIConfig { - var folder string if dirlist := acct.Directories(); dirlist != nil { - folder = dirlist.Selected() + return dirlist.UiConfig() } - return acct.conf.GetUiConfig(map[config.ContextType]string{ - config.UI_CONTEXT_ACCOUNT: acct.AccountConfig().Name, - config.UI_CONTEXT_FOLDER: folder, - }) + return acct.uiConf } func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountConfig, @@ -61,6 +58,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon host: host, logger: logger, state: statusline.NewState(acct.Name, len(conf.Accounts) > 1, conf.Statusline), + uiConf: acctUiConf, } view.grid = ui.NewGrid().Rows([]ui.GridSpec{ diff --git a/widgets/dirlist.go b/widgets/dirlist.go index 006771a..ad5f048 100644 --- a/widgets/dirlist.go +++ b/widgets/dirlist.go @@ -44,6 +44,8 @@ type DirectoryLister interface { SetMsgStore(string, *lib.MessageStore) FilterDirs([]string, []string, bool) []string + + UiConfig() *config.UIConfig } type DirectoryList struct { @@ -61,6 +63,7 @@ type DirectoryList struct { skipSelect context.Context skipSelectCancel context.CancelFunc connected bool + uiConf map[string]*config.UIConfig } func NewDirectoryList(conf *config.AercConfig, acctConf *config.AccountConfig, @@ -68,6 +71,8 @@ func NewDirectoryList(conf *config.AercConfig, acctConf *config.AccountConfig, ) DirectoryLister { ctx, cancel := context.WithCancel(context.Background()) + uiConfMap := make(map[string]*config.UIConfig) + dirlist := &DirectoryList{ aercConf: conf, acctConf: acctConf, @@ -76,6 +81,7 @@ func NewDirectoryList(conf *config.AercConfig, acctConf *config.AccountConfig, worker: worker, skipSelect: ctx, skipSelectCancel: cancel, + uiConf: uiConfMap, } uiConf := dirlist.UiConfig() dirlist.spinner = NewSpinner(uiConf) @@ -92,10 +98,15 @@ func NewDirectoryList(conf *config.AercConfig, acctConf *config.AccountConfig, } func (dirlist *DirectoryList) UiConfig() *config.UIConfig { - return dirlist.aercConf.GetUiConfig(map[config.ContextType]string{ + if ui, ok := dirlist.uiConf[dirlist.Selected()]; ok { + return ui + } + ui := dirlist.aercConf.GetUiConfig(map[config.ContextType]string{ config.UI_CONTEXT_ACCOUNT: dirlist.acctConf.Name, config.UI_CONTEXT_FOLDER: dirlist.Selected(), }) + dirlist.uiConf[dirlist.Selected()] = ui + return ui } func (dirlist *DirectoryList) List() []string { diff --git a/widgets/msglist.go b/widgets/msglist.go index df24526..ec14e79 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -194,14 +194,23 @@ func (ml *MessageList) drawRow(textWidth int, ctx *ui.Context, uid uint32, row i return false } - confParams := map[config.ContextType]string{ - config.UI_CONTEXT_ACCOUNT: acct.AccountConfig().Name, - config.UI_CONTEXT_FOLDER: acct.Directories().Selected(), - } - if msg.Envelope != nil { - confParams[config.UI_CONTEXT_SUBJECT] = msg.Envelope.Subject + // TODO deprecate subject contextual UIs? Only related setting is styleset, + // should implement a better per-message styling method + // Check if we have any applicable ContextualUIConfigs + confs := ml.aerc.conf.GetContextualUIConfigs() + uiConfig := acct.Directories().UiConfig() + for _, c := range confs { + if c.ContextType == config.UI_CONTEXT_SUBJECT && msg.Envelope != nil { + if c.Regex.Match([]byte(msg.Envelope.Subject)) { + confParams := map[config.ContextType]string{ + config.UI_CONTEXT_ACCOUNT: acct.AccountConfig().Name, + config.UI_CONTEXT_FOLDER: acct.Directories().Selected(), + config.UI_CONTEXT_SUBJECT: msg.Envelope.Subject, + } + uiConfig = ml.conf.GetUiConfig(confParams) + } + } } - uiConfig := ml.conf.GetUiConfig(confParams) msg_styles := []config.StyleObject{} // unread message |