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>
This commit is contained in:
parent
d45c07eb6a
commit
4240f1fbfd
4 changed files with 36 additions and 14 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
if msg.Envelope != nil {
|
||||
confParams[config.UI_CONTEXT_SUBJECT] = msg.Envelope.Subject
|
||||
}
|
||||
uiConfig := ml.conf.GetUiConfig(confParams)
|
||||
|
||||
msg_styles := []config.StyleObject{}
|
||||
// unread message
|
||||
|
|
Loading…
Reference in a new issue