@@ -26,32 +26,34 @@ local M = {}
26
26
--- @field modname string Name of the module
27
27
--- @field stat ? uv_fs_t File stat of the module path
28
28
29
- M .VERSION = 3
29
+ --- @alias LoaderStats table<string , { total : number , time : number , [string] : number ?}? >
30
+
30
31
M .path = vim .fn .stdpath (" cache" ) .. " /luac"
31
32
M .enabled = false
32
- --- @type table<string , { total : number , time : number , [string] : number ?}? >
33
- M .stats = {
34
- find = { total = 0 , time = 0 , not_found = 0 },
35
- }
36
33
37
34
--- @class Loader
38
35
--- @field _rtp string[]
39
36
--- @field _rtp_pure string[]
40
37
--- @field _rtp_key string
41
38
local Loader = {
39
+ VERSION = 3 ,
42
40
--- @type table<string , table<string,ModuleInfo>>
43
41
_indexed = {},
44
42
--- @type table<string , string[]>
45
43
_topmods = {},
46
44
_loadfile = loadfile ,
45
+ --- @type LoaderStats
46
+ _stats = {
47
+ find = { total = 0 , time = 0 , not_found = 0 },
48
+ },
47
49
}
48
50
49
51
--- Tracks the time spent in a function
50
52
--- @private
51
- function M . _track (stat , start )
52
- M . stats [stat ] = M . stats [stat ] or { total = 0 , time = 0 }
53
- M . stats [stat ].total = M . stats [stat ].total + 1
54
- M . stats [stat ].time = M . stats [stat ].time + uv .hrtime () - start
53
+ function Loader . track (stat , start )
54
+ Loader . _stats [stat ] = Loader . _stats [stat ] or { total = 0 , time = 0 }
55
+ Loader . _stats [stat ].total = Loader . _stats [stat ].total + 1
56
+ Loader . _stats [stat ].time = Loader . _stats [stat ].time + uv .hrtime () - start
55
57
end
56
58
57
59
--- slightly faster/different version than vim.fs.normalize
77
79
function Loader .get_rtp ()
78
80
local start = uv .hrtime ()
79
81
if vim .in_fast_event () then
80
- M . _track (" get_rtp" , start )
82
+ Loader . track (" get_rtp" , start )
81
83
return (Loader ._rtp or {}), false
82
84
end
83
85
local updated = false
@@ -94,7 +96,7 @@ function Loader.get_rtp()
94
96
updated = true
95
97
Loader ._rtp_key = key
96
98
end
97
- M . _track (" get_rtp" , start )
99
+ Loader . track (" get_rtp" , start )
98
100
return Loader ._rtp , updated
99
101
end
100
102
@@ -115,7 +117,7 @@ function Loader.write(name, entry)
115
117
local cname = Loader .cache_file (name )
116
118
local f = assert (uv .fs_open (cname , " w" , 438 ))
117
119
local header = {
118
- M .VERSION ,
120
+ Loader .VERSION ,
119
121
entry .hash .size ,
120
122
entry .hash .mtime .sec ,
121
123
entry .hash .mtime .nsec ,
@@ -142,16 +144,16 @@ function Loader.read(name)
142
144
143
145
--- @type integer[] |{ [0] : integer }
144
146
local header = vim .split (data :sub (1 , zero - 1 ), " ," )
145
- if tonumber (header [1 ]) ~= M .VERSION then
147
+ if tonumber (header [1 ]) ~= Loader .VERSION then
146
148
return
147
149
end
148
- M . _track (" read" , start )
150
+ Loader . track (" read" , start )
149
151
return {
150
152
hash = { size = tonumber (header [2 ]), mtime = { sec = tonumber (header [3 ]), nsec = tonumber (header [4 ]) } },
151
153
chunk = data :sub (zero + 1 ),
152
154
}
153
155
end
154
- M . _track (" read" , start )
156
+ Loader . track (" read" , start )
155
157
end
156
158
157
159
--- The `package.loaders` loader for lua files using the cache.
@@ -163,10 +165,10 @@ function Loader.loader(modname)
163
165
local ret = M .find (modname )[1 ]
164
166
if ret then
165
167
local chunk , err = Loader .load (ret .modpath , { hash = ret .stat })
166
- M . _track (" loader" , start )
168
+ Loader . track (" loader" , start )
167
169
return chunk or error (err )
168
170
end
169
- M . _track (" loader" , start )
171
+ Loader . track (" loader" , start )
170
172
return " \n cache_loader: module " .. modname .. " not found"
171
173
end
172
174
@@ -189,10 +191,10 @@ function Loader.loader_lib(modname)
189
191
local dash = modname :find (" -" , 1 , true )
190
192
local funcname = dash and modname :sub (dash + 1 ) or modname
191
193
local chunk , err = package.loadlib (ret .modpath , " luaopen_" .. funcname :gsub (" %." , " _" ))
192
- M . _track (" loader_lib" , start )
194
+ Loader . track (" loader_lib" , start )
193
195
return chunk or error (err )
194
196
end
195
- M . _track (" loader_lib" , start )
197
+ Loader . track (" loader_lib" , start )
196
198
return " \n cache_loader_lib: module " .. modname .. " not found"
197
199
end
198
200
@@ -209,7 +211,7 @@ function Loader.loadfile(filename, mode, env, hash)
209
211
filename = Loader .normalize (filename )
210
212
mode = nil -- ignore mode, since we byte-compile the lua source files
211
213
local chunk , err = Loader .load (filename , { mode = mode , env = env , hash = hash })
212
- M . _track (" loadfile" , start )
214
+ Loader . track (" loadfile" , start )
213
215
return chunk , err
214
216
end
215
217
@@ -244,7 +246,7 @@ function Loader.load(modpath, opts)
244
246
if not hash then
245
247
-- trigger correct error
246
248
chunk , err = Loader ._loadfile (modpath , opts .mode , opts .env )
247
- M . _track (" load" , start )
249
+ Loader . track (" load" , start )
248
250
return chunk , err
249
251
end
250
252
@@ -254,7 +256,7 @@ function Loader.load(modpath, opts)
254
256
-- selene: allow(incorrect_standard_library_use)
255
257
chunk , err = load (entry .chunk --[[ @as string]] , " @" .. modpath , opts .mode , opts .env )
256
258
if not (err and err :find (" cannot load incompatible bytecode" , 1 , true )) then
257
- M . _track (" load" , start )
259
+ Loader . track (" load" , start )
258
260
return chunk , err
259
261
end
260
262
end
@@ -265,7 +267,7 @@ function Loader.load(modpath, opts)
265
267
entry .chunk = string.dump (chunk )
266
268
Loader .write (modpath , entry )
267
269
end
268
- M . _track (" load" , start )
270
+ Loader . track (" load" , start )
269
271
return chunk , err
270
272
end
271
273
@@ -332,7 +334,7 @@ function M.find(modname, opts)
332
334
elseif Loader .lsmod (path )[topmod ] then
333
335
for _ , pattern in ipairs (patterns ) do
334
336
local modpath = path .. pattern
335
- M . stats .find .stat = (M . stats .find .stat or 0 ) + 1
337
+ Loader . _stats .find .stat = (Loader . _stats .find .stat or 0 ) + 1
336
338
local hash = uv .fs_stat (modpath )
337
339
if hash then
338
340
results [# results + 1 ] = { modpath = modpath , stat = hash , modname = modname }
@@ -361,10 +363,10 @@ function M.find(modname, opts)
361
363
_find (opts .paths )
362
364
end
363
365
364
- M . _track (" find" , start )
366
+ Loader . track (" find" , start )
365
367
if # results == 0 then
366
368
-- module not found
367
- M . stats .find .not_found = M . stats .find .not_found + 1
369
+ Loader . _stats .find .not_found = Loader . _stats .find .not_found + 1
368
370
end
369
371
370
372
return results
@@ -474,57 +476,60 @@ function Loader.lsmod(path)
474
476
end
475
477
end
476
478
end
477
- M . _track (" lsmod" , start )
479
+ Loader . track (" lsmod" , start )
478
480
end
479
481
return Loader ._indexed [path ]
480
482
end
481
483
482
484
--- Debug function that wrapps all loaders and tracks stats
483
485
--- @private
484
- function M .profile_loaders ()
486
+ function M ._profile_loaders ()
485
487
for l , loader in pairs (package.loaders ) do
486
488
local loc = debug.getinfo (loader , " Sn" ).source :sub (2 )
487
489
package.loaders [l ] = function (modname )
488
490
local start = vim .loop .hrtime ()
489
491
local ret = loader (modname )
490
- M . _track (" loader " .. l .. " : " .. loc , start )
491
- M . _track (" loader_all" , start )
492
+ Loader . track (" loader " .. l .. " : " .. loc , start )
493
+ Loader . track (" loader_all" , start )
492
494
return ret
493
495
end
494
496
end
495
497
end
496
498
497
499
--- Prints all cache stats
500
+ --- @param opts ? { print ?: boolean }
501
+ --- @return LoaderStats
498
502
--- @private
499
- function M .inspect ()
500
- --- @private
501
- local function ms (nsec )
502
- return math.floor (nsec / 1e6 * 1000 + 0.5 ) / 1000 .. " ms"
503
- end
504
- local chunks = {} --- @type string[][]
505
- --- @type string[]
506
- local stats = vim .tbl_keys (M .stats )
507
- table.sort (stats )
508
- for _ , stat in ipairs (stats ) do
509
- vim .list_extend (chunks , {
510
- { " \n " .. stat .. " \n " , " Title" },
511
- { " * total: " },
512
- { tostring (M .stats [stat ].total ) .. " \n " , " Number" },
513
- { " * time: " },
514
- { ms (M .stats [stat ].time ) .. " \n " , " Bold" },
515
- { " * avg time: " },
516
- { ms (M .stats [stat ].time / M .stats [stat ].total ) .. " \n " , " Bold" },
517
- })
518
- for k , v in pairs (M .stats [stat ]) do
519
- if not vim .tbl_contains ({ " time" , " total" }, k ) then
520
- chunks [# chunks + 1 ] = { " * " .. k .. " :" .. string.rep (" " , 9 - # k ) }
521
- chunks [# chunks + 1 ] = { tostring (v ) .. " \n " , " Number" }
503
+ function M ._inspect (opts )
504
+ if opts and opts .print then
505
+ --- @private
506
+ local function ms (nsec )
507
+ return math.floor (nsec / 1e6 * 1000 + 0.5 ) / 1000 .. " ms"
508
+ end
509
+ local chunks = {} --- @type string[][]
510
+ --- @type string[]
511
+ local stats = vim .tbl_keys (Loader ._stats )
512
+ table.sort (stats )
513
+ for _ , stat in ipairs (stats ) do
514
+ vim .list_extend (chunks , {
515
+ { " \n " .. stat .. " \n " , " Title" },
516
+ { " * total: " },
517
+ { tostring (Loader ._stats [stat ].total ) .. " \n " , " Number" },
518
+ { " * time: " },
519
+ { ms (Loader ._stats [stat ].time ) .. " \n " , " Bold" },
520
+ { " * avg time: " },
521
+ { ms (Loader ._stats [stat ].time / Loader ._stats [stat ].total ) .. " \n " , " Bold" },
522
+ })
523
+ for k , v in pairs (Loader ._stats [stat ]) do
524
+ if not vim .tbl_contains ({ " time" , " total" }, k ) then
525
+ chunks [# chunks + 1 ] = { " * " .. k .. " :" .. string.rep (" " , 9 - # k ) }
526
+ chunks [# chunks + 1 ] = { tostring (v ) .. " \n " , " Number" }
527
+ end
522
528
end
523
529
end
530
+ vim .api .nvim_echo (chunks , true , {})
524
531
end
525
- vim . api . nvim_echo ( chunks , true , {})
532
+ return Loader . _stats
526
533
end
527
534
528
- M ._Cache = Loader
529
-
530
535
return M
0 commit comments