Skip to content

Commit 7e6af36

Browse files
feat: additional startup performance improvements
## Details Additional changes made with the goal of reducing the startup time of this plugin. The main idea in this set of changes is to avoid requiring modules at the top of files until they are actually needed. To accomplish this we have: - gone back to storing global information in the `state` module, that way we are not calling `setup` in order to provide data to various modules that need it, instead they will go back to picking it up from `state` fields that are shared, has some drawbacks but overall fine - for various one off `require` statements (i.e. only used once in a given module) inline the `require` statement within the function that uses it, particularly helpful with the request `Context` fields and running `handlers` Overall the improvement seems to be around 2x, give or take. Where previously we were starting up in around 3.0ms, it is now closer to 1.5ms, which is a nice bump. Most of the remaining time is spent loading the large `settings` module, and the impact of all the things we do need to load immediately, times are around 0.5ms and 1.0ms respectively.
1 parent 06c7598 commit 7e6af36

File tree

10 files changed

+70
-146
lines changed

10 files changed

+70
-146
lines changed

lua/render-markdown/core/handlers.lua

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
local iter = require('render-markdown.lib.iter')
22
local log = require('render-markdown.core.log')
3-
4-
---@class render.md.handlers.Config
5-
---@field nested boolean
6-
---@field custom table<string, render.md.Handler>
3+
local state = require('render-markdown.state')
74

85
---@class render.md.Handlers
9-
---@field private config render.md.handlers.Config
106
local M = {}
117

128
---@private
@@ -19,12 +15,6 @@ M.builtin = {
1915
yaml = require('render-markdown.handler.yaml'),
2016
}
2117

22-
---called from state on setup
23-
---@param config render.md.handlers.Config
24-
function M.setup(config)
25-
M.config = config
26-
end
27-
2818
---@param context render.md.request.Context
2919
---@param parser vim.treesitter.LanguageTree
3020
---@return render.md.Mark[]
@@ -34,8 +24,8 @@ function M.run(context, parser)
3424
local root = tree:root()
3525
local language = language_tree:lang()
3626
if
37-
(M.config.custom[language] or M.builtin[language])
38-
and (M.config.nested or M.level(language_tree) == 1)
27+
(state.custom_handlers[language] or M.builtin[language])
28+
and (state.nested or M.level(language_tree) == 1)
3929
and context.view:overlaps(root)
4030
then
4131
local roots = language_roots[language]
@@ -90,7 +80,7 @@ end
9080
---@param ctx render.md.handler.Context
9181
function M.tree(marks, language, ctx)
9282
log.buf('trace', 'Language', ctx.buf, language)
93-
local custom = M.config.custom[language]
83+
local custom = state.custom_handlers[language]
9484
if custom then
9585
log.buf('trace', 'Handler', ctx.buf, 'custom')
9686
vim.list_extend(marks, custom.parse(ctx))

lua/render-markdown/core/log.lua

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
local env = require('render-markdown.lib.env')
2+
local state = require('render-markdown.state')
23

34
---@class render.md.log.Entry
45
---@field date string
56
---@field level string
67
---@field name string
78
---@field message string
89

9-
---@class render.md.log.Config
10-
---@field level render.md.log.Level
11-
---@field runtime boolean
12-
1310
---@enum (key) render.md.log.Level
1411
local Level = {
1512
trace = 0,
@@ -23,20 +20,13 @@ local Level = {
2320
---@class render.md.Log
2421
---@field private file string
2522
---@field private entries render.md.log.Entry[]
26-
---@field private config render.md.log.Config
2723
local M = {}
2824

29-
---called from state on setup
30-
---@param config render.md.log.Config
31-
function M.setup(config)
25+
---called from plugin directory
26+
function M.init()
3227
-- typically resolves to ~/.local/state/nvim/render-markdown.log
3328
M.file = vim.fn.stdpath('state') .. '/render-markdown.log'
3429
M.entries = {}
35-
M.config = config
36-
end
37-
38-
---called from plugin directory
39-
function M.init()
4030
-- clear the file contents if it is too big
4131
if env.file_size_mb(M.file) > 5 then
4232
assert(io.open(M.file, 'w')):close()
@@ -52,7 +42,7 @@ end
5242
---@param callback fun()
5343
---@return fun()
5444
function M.runtime(name, callback)
55-
if M.config.runtime then
45+
if state.log_runtime then
5646
return function()
5747
local compat = require('render-markdown.lib.compat')
5848
local start_time = compat.uv.hrtime()
@@ -122,7 +112,7 @@ end
122112
---@param name string
123113
---@param ... any
124114
function M.add(level, name, ...)
125-
if M.level(level) < M.level(M.config.level) then
115+
if M.level(level) < M.level(state.log_level) then
126116
return
127117
end
128118
local messages = {} ---@type string[]

lua/render-markdown/core/manager.lua

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,7 @@ local log = require('render-markdown.core.log')
33
local state = require('render-markdown.state')
44
local ui = require('render-markdown.core.ui')
55

6-
---@class render.md.manager.Config
7-
---@field file_types string[]
8-
---@field ignore fun(buf: integer): boolean
9-
---@field change_events string[]
10-
---@field on render.md.on.Config
11-
---@field completions render.md.completions.Config
12-
136
---@class render.md.Manager
14-
---@field private config render.md.manager.Config
157
local M = {}
168

179
---@private
@@ -21,12 +13,6 @@ M.group = vim.api.nvim_create_augroup('RenderMarkdown', {})
2113
---@type integer[]
2214
M.buffers = {}
2315

24-
---called from state on setup
25-
---@param config render.md.manager.Config
26-
function M.setup(config)
27-
M.config = config
28-
end
29-
3016
---called from plugin directory
3117
function M.init()
3218
-- lazy loading: ignores current buffer as FileType event already executed
@@ -99,13 +85,13 @@ function M.attach(buf)
9985
end
10086

10187
local config = state.get(buf)
102-
M.config.on.attach({ buf = buf })
88+
state.on.attach({ buf = buf })
10389
require('render-markdown.core.ts').init()
104-
if M.config.completions.lsp.enabled then
90+
if state.completions.lsp.enabled then
10591
require('render-markdown.integ.lsp').init()
106-
elseif M.config.completions.blink.enabled then
92+
elseif state.completions.blink.enabled then
10793
require('render-markdown.integ.blink').init()
108-
elseif M.config.completions.coq.enabled then
94+
elseif state.completions.coq.enabled then
10995
require('render-markdown.integ.coq').init()
11096
else
11197
require('render-markdown.integ.cmp').init()
@@ -127,7 +113,7 @@ function M.attach(buf)
127113
events[#events + 1] = 'CursorMovedI'
128114
events[#events + 1] = 'TextChangedI'
129115
end
130-
local force = M.config.change_events
116+
local force = state.change_events
131117
for _, event in ipairs(force) do
132118
if not vim.tbl_contains(events, event) then
133119
events[#events + 1] = event
@@ -173,7 +159,7 @@ function M.should_attach(buf)
173159
end
174160

175161
local file_type = env.buf.get(buf, 'filetype')
176-
local file_types = M.config.file_types
162+
local file_types = state.file_types
177163
if not vim.tbl_contains(file_types, file_type) then
178164
local reason = ('%s /∈ %s'):format(file_type, vim.inspect(file_types))
179165
log.attach(buf, 'skip', 'file type', reason)
@@ -188,7 +174,7 @@ function M.should_attach(buf)
188174
return false
189175
end
190176

191-
if M.config.ignore(buf) then
177+
if state.ignore(buf) then
192178
log.attach(buf, 'skip', 'user ignore')
193179
return false
194180
end

lua/render-markdown/core/ts.lua

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
local compat = require('render-markdown.lib.compat')
2-
3-
---@class render.md.ts.Config
4-
---@field file_types string[]
5-
---@field restart_highlighter boolean
6-
---@field injections table<string, render.md.injection.Config>
7-
---@field patterns table<string, render.md.pattern.Config>
2+
local state = require('render-markdown.state')
83

94
---@class render.md.Ts
10-
---@field private config render.md.ts.Config
115
local M = {}
126

137
---@private
@@ -19,10 +13,8 @@ M.initialized = false
1913
M.queries = {}
2014

2115
---called from state on setup
22-
---@param config render.md.ts.Config
23-
function M.setup(config)
24-
M.config = config
25-
for _, language in ipairs(M.config.file_types) do
16+
function M.setup()
17+
for _, language in ipairs(state.file_types) do
2618
M.inject(language)
2719
end
2820
end
@@ -33,10 +25,10 @@ function M.init()
3325
return
3426
end
3527
M.initialized = true
36-
for _, language in ipairs(M.config.file_types) do
28+
for _, language in ipairs(state.file_types) do
3729
M.disable(language)
3830
end
39-
if M.config.restart_highlighter then
31+
if state.restart_highlighter then
4032
vim.treesitter.stop()
4133
vim.treesitter.start()
4234
end
@@ -57,7 +49,7 @@ end
5749
---@private
5850
---@param language string
5951
function M.inject(language)
60-
local injection = M.config.injections[language]
52+
local injection = state.injections[language]
6153
if not injection or not injection.enabled then
6254
return
6355
end
@@ -80,7 +72,7 @@ end
8072
---@private
8173
---@param language string
8274
function M.disable(language)
83-
local pattern = M.config.patterns[language]
75+
local pattern = state.patterns[language]
8476
if not pattern or not pattern.disable then
8577
return
8678
end

lua/render-markdown/core/ui.lua

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
local Context = require('render-markdown.request.context')
2-
local Decorator = require('render-markdown.lib.decorator')
3-
local Extmark = require('render-markdown.lib.extmark')
42
local compat = require('render-markdown.lib.compat')
53
local env = require('render-markdown.lib.env')
6-
local handlers = require('render-markdown.core.handlers')
74
local iter = require('render-markdown.lib.iter')
85
local log = require('render-markdown.core.log')
96
local state = require('render-markdown.state')
107

11-
---@class render.md.ui.Config
12-
---@field on render.md.on.Config
13-
148
---@class render.md.Ui
15-
---@field private config render.md.ui.Config
169
local M = {}
1710

1811
M.ns = vim.api.nvim_create_namespace('render-markdown.nvim')
@@ -22,9 +15,7 @@ M.ns = vim.api.nvim_create_namespace('render-markdown.nvim')
2215
M.cache = {}
2316

2417
---called from state on setup
25-
---@param config render.md.ui.Config
26-
function M.setup(config)
27-
M.config = config
18+
function M.setup()
2819
-- clear marks and reset cache
2920
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
3021
vim.api.nvim_buf_clear_namespace(buf, M.ns, 0, -1)
@@ -37,7 +28,7 @@ end
3728
function M.get(buf)
3829
local result = M.cache[buf]
3930
if not result then
40-
result = Decorator.new(buf)
31+
result = require('render-markdown.lib.decorator').new(buf)
4132
M.cache[buf] = result
4233
end
4334
return result
@@ -133,7 +124,7 @@ function Updater:clear()
133124
extmark:hide(M.ns, self.buf)
134125
end
135126
vim.api.nvim_buf_clear_namespace(self.buf, M.ns, 0, -1)
136-
M.config.on.clear({ buf = self.buf, win = self.win })
127+
state.on.clear({ buf = self.buf, win = self.win })
137128
end
138129

139130
---@private
@@ -148,7 +139,7 @@ function Updater:render()
148139
self.decorator:set(extmarks)
149140
if initial then
150141
compat.fix_lsp_window(self.buf, self.win, extmarks)
151-
M.config.on.initial({ buf = self.buf, win = self.win })
142+
state.on.initial({ buf = self.buf, win = self.win })
152143
end
153144
self:display()
154145
end)
@@ -167,6 +158,8 @@ function Updater:parse(callback)
167158
if context then
168159
-- make sure injections are processed
169160
context.view:parse(parser, function()
161+
local Extmark = require('render-markdown.lib.extmark')
162+
local handlers = require('render-markdown.core.handlers')
170163
local marks = handlers.run(context, parser)
171164
callback(iter.list.map(marks, Extmark.new))
172165
end)
@@ -191,7 +184,7 @@ function Updater:display()
191184
extmark:show(M.ns, self.buf)
192185
end
193186
end
194-
M.config.on.render({ buf = self.buf, win = self.win })
187+
state.on.render({ buf = self.buf, win = self.win })
195188
end
196189

197190
---@private

lua/render-markdown/health.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ local state = require('render-markdown.state')
66
local M = {}
77

88
---@private
9-
M.version = '8.8.11'
9+
M.version = '8.8.12'
1010

1111
function M.check()
1212
M.start('versions')

lua/render-markdown/integ/blink.lua

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
local source = require('render-markdown.integ.source')
2-
3-
---@class render.md.source.blink.Config
4-
---@field file_types string[]
2+
local state = require('render-markdown.state')
53

64
---@class render.md.blink.Source: blink.cmp.Source
7-
---@field private config render.md.source.blink.Config
85
local Source = {}
96
Source.__index = Source
107

118
---@private
129
---@type boolean
1310
Source.initialized = false
1411

15-
---called from state on setup
16-
---@param config render.md.source.blink.Config
17-
function Source.setup(config)
18-
Source.config = config
19-
end
20-
2112
---called from manager on buffer attach
2213
function Source.init()
2314
if Source.initialized then
@@ -33,7 +24,7 @@ function Source.init()
3324
name = 'RenderMarkdown',
3425
module = 'render-markdown.integ.blink',
3526
})
36-
for _, file_type in ipairs(Source.config.file_types) do
27+
for _, file_type in ipairs(state.file_types) do
3728
pcall(blink.add_filetype_source, file_type, id)
3829
end
3930
end

lua/render-markdown/integ/source.lua

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,9 @@ local children = vim.list_extend(vim.tbl_keys(markers), {
1919

2020
local siblings = { 'paragraph' }
2121

22-
---@class render.md.source.Config
23-
---@field completions render.md.completions.Config
24-
2522
---@class render.md.Source
26-
---@field private config render.md.source.Config
2723
local M = {}
2824

29-
---called from state on setup
30-
---@param config render.md.source.Config
31-
function M.setup(config)
32-
M.config = config
33-
end
34-
3525
---@return boolean
3626
function M.enabled()
3727
return manager.attached(env.buf.current())
@@ -68,7 +58,7 @@ function M.items(buf, row, col)
6858

6959
local items = {} ---@type lsp.CompletionItem[]
7060
local config = state.get(buf)
71-
local filter = M.config.completions.filter
61+
local filter = state.completions.filter
7262
local prefix = line:sub(before, before) == ' ' and '' or ' '
7363
if node.type == 'block_quote' then
7464
local suffix = ''

0 commit comments

Comments
 (0)