perf(picker.frecency): cache all deadlines on load

This commit is contained in:
Folke Lemaitre 2025-01-23 23:25:16 +01:00
parent c2916cb526
commit 5b3625bcea
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
3 changed files with 25 additions and 4 deletions

View file

@ -1,8 +1,8 @@
-- Frecency based on exponential decay. Roughly based on:
-- https://wiki.mozilla.org/User:Jesse/NewFrecency?title=User:Jesse/NewFrecency
---@class snacks.picker.Frecency
---@field store table<string, number>
---@field now number
---@field cache table<string, number>
local M = {}
M.__index = M
@ -19,6 +19,7 @@ local MAX_STORE_SIZE = 10000
---@field set fun(self:snacks.picker.frecency.Store, key:string, value:number)
---@field get fun(self:snacks.picker.frecency.Store, key:string):number
---@field close fun(self:snacks.picker.frecency.Store)
---@field get_all fun(self:snacks.picker.frecency.Store):table<string, number>
-- Global store of frecency deadlinesl
---@type snacks.picker.frecency.Store?
@ -28,7 +29,7 @@ function M.setup()
if
not pcall(function()
local db = require("snacks.picker.util.db").new(store_file .. ".sqlite3", "number")
M.store = db
M.store = db --[[@as snacks.picker.frecency.Store]]
-- Cleanup old entries
local cutoff = db:prepare("SELECT value FROM data ORDER BY value DESC LIMIT 1 OFFSET ?;")
if cutoff:exec({ MAX_STORE_SIZE - 1 }) == 100 then -- 100 == SQLITE_ROW
@ -36,7 +37,7 @@ function M.setup()
end
end)
then
M.store = require("snacks.picker.util.kv").new(store_file .. ".dat", { max_size = MAX_STORE_SIZE })
M.store = require("snacks.picker.util.kv").new(store_file .. ".dat", { max_size = MAX_STORE_SIZE }) --[[@as snacks.picker.frecency.Store]]
end
local group = vim.api.nvim_create_augroup("snacks_picker_frecency", {})
@ -67,6 +68,7 @@ function M.new()
if not M.store then
M.setup()
end
self.cache = M.store:get_all()
return self
end
@ -94,7 +96,7 @@ function M:get(item, opts)
if not path then
return 0
end
local deadline = self.store:get(path)
local deadline = self.cache[path]
if not deadline then
return opts.seed ~= false and self:seed(item) or 0
end

View file

@ -86,6 +86,7 @@ function Query:exec(binds)
return self:step()
end
---@return number
function Query:step()
return sqlite.sqlite3_step(self.stmt)
end
@ -204,4 +205,18 @@ function M:count()
end
end
function M:get_all()
local query = self:prepare("SELECT key, value FROM data;")
local ret = {} ---@type table<string, any>
local code = query:exec()
while code == 100 do -- 100 == SQLITE_ROW
local k = query:col("string", 0) -- key is always a string
local v = query:col(self.type, 1) -- value type is whatever you set
ret[k] = v
code = query:step()
end
query:close()
return ret
end
return M

View file

@ -42,6 +42,10 @@ function M:get(key)
return self.data[key]
end
function M:get_all()
return self.data
end
function M:close()
vim.fn.mkdir(vim.fn.fnamemodify(self.path, ":h"), "p")
local stat = uv.fs_stat(self.path)