perf(fs): normalize path only once in fs.dir

Re-normalizing a path after a `joinpath` isn't necessary. Calling
`normalize` on each child directory had quite a bit of impact when
traversing a large directory.

A simple test showed:

Before: ~144ms
After: ~80ms

running the following logic against a dir with 4367 child folders and
25826 files:

    local files = {}
    local start = uv.hrtime()
    for name, type in vim.fs.dir(path, { depth = max_depth }) do
      table.insert(files, { name, type })
    end
    local duration = uv.hrtime() - start

Relates to https://github.com/neovim/neovim/issues/23291
This commit is contained in:
Mathias Fussenegger 2024-05-13 17:26:57 +02:00 committed by Lewis Russell
parent e889f6781b
commit 8bb67d64e2

View File

@ -120,8 +120,9 @@ function M.dir(path, opts)
skip = { opts.skip, { 'function' }, true },
})
path = M.normalize(path)
if not opts.depth or opts.depth == 1 then
local fs = vim.uv.fs_scandir(M.normalize(path))
local fs = vim.uv.fs_scandir(path)
return function()
if not fs then
return
@ -137,7 +138,7 @@ function M.dir(path, opts)
--- @type string, integer
local dir0, level = unpack(table.remove(dirs, 1))
local dir = level == 1 and dir0 or M.joinpath(path, dir0)
local fs = vim.uv.fs_scandir(M.normalize(dir))
local fs = vim.uv.fs_scandir(dir)
while fs do
local name, t = vim.uv.fs_scandir_next(fs)
if not name then