mirror of
				https://github.com/folke/lazy.nvim.git
				synced 2025-10-31 06:21:14 +00:00 
			
		
		
		
	feat(profile): added accurate startuptime to ui/stats/docs
This commit is contained in:
		
					parent
					
						
							
								d1739cb7e1
							
						
					
				
			
			
				commit
				
					
						a2fdf369f2
					
				
			
		
					 6 changed files with 103 additions and 11 deletions
				
			
		
							
								
								
									
										20
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								README.md
									
										
									
									
									
								
							|  | @ -500,13 +500,25 @@ $ nvim --headless "+Lazy! sync" +qa | |||
| - **plugins**: a list of plugin names to run the operation on | ||||
| - **concurrency**: limit the `number` of concurrently running tasks | ||||
| 
 | ||||
| If you want to display the number of plugins on your dashboard, you can use | ||||
| this simple API: | ||||
| Stats API (`require("lazy").stats()`): | ||||
| 
 | ||||
| <!-- stats:start --> | ||||
| 
 | ||||
| ```lua | ||||
| local plugins = require("lazy").stats().count | ||||
| { | ||||
|   -- startuptime in milliseconds till UIEnter | ||||
|   startuptime = 0, | ||||
|   -- when true, startuptime is the accurate cputime for the Neovim process. (Linux & Macos) | ||||
|   -- this is more accurate than `nvim --startuptime`, and as such will be slightly higher | ||||
|   -- when false, startuptime is calculated based on a delta with a timestamp when lazy started. | ||||
|   startuptime_cputime = false, | ||||
|   count = 0, -- total number of plugins | ||||
|   loaded = 0, -- number of loaded plugins | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| <!-- stats:end --> | ||||
| 
 | ||||
| **lazy.nvim** provides a statusline component that you can use to show the number of pending updates. | ||||
| Make sure to enable `config.checker.enabled = true` to make this work. | ||||
| 
 | ||||
|  | @ -543,6 +555,8 @@ The following user events will be triggered: | |||
| - **LazyLog**: after running log | ||||
| - **LazyReload**: triggered by change detection after reloading plugin specs | ||||
| - **VeryLazy**: triggered after `LazyDone` and processing `VimEnter` auto commands | ||||
| - **LazyVimStarted**: triggered after `UIEnter` when `require("lazy").stats().startuptime` has been calculated. | ||||
|   Useful to update the startuptime on your dashboard. | ||||
| 
 | ||||
| ## 🔒 Lockfile `lazy-lock.json` | ||||
| 
 | ||||
|  |  | |||
|  | @ -200,6 +200,12 @@ function M.setup(spec, opts) | |||
|   if M.headless then | ||||
|     require("lazy.view.commands").setup() | ||||
|   else | ||||
|     vim.api.nvim_create_autocmd("UIEnter", { | ||||
|       callback = function() | ||||
|         require("lazy.stats").on_ui_enter() | ||||
|       end, | ||||
|     }) | ||||
| 
 | ||||
|     vim.api.nvim_create_autocmd("User", { | ||||
|       pattern = "VeryLazy", | ||||
|       once = true, | ||||
|  |  | |||
|  | @ -126,6 +126,7 @@ function M.update() | |||
|   config = config:gsub("%s*debug = false.\n", "\n") | ||||
|   M.save({ | ||||
|     bootstrap = M.extract("lua/lazy/init.lua", "function M%.bootstrap%(%)\n(.-)\nend"), | ||||
|     stats = M.extract("lua/lazy/stats.lua", "\nM%._stats = ({.-\n})"), | ||||
|     config = config, | ||||
|     spec = Util.read_file("lua/lazy/example.lua"), | ||||
|     commands = M.commands(), | ||||
|  |  | |||
|  | @ -1,9 +1,11 @@ | |||
| ---@type LazyCommands | ||||
| local M = {} | ||||
| M._start = 0 | ||||
| 
 | ||||
| ---@param spec LazySpec Should be a module name to load, or a plugin spec | ||||
| ---@param opts? LazyConfig | ||||
| function M.setup(spec, opts) | ||||
|   M._start = M._start == 0 and vim.loop.hrtime() or M._start | ||||
|   if vim.g.lazy_did_setup then | ||||
|     return vim.notify( | ||||
|       "Re-sourcing your config is not supported with lazy.nvim", | ||||
|  | @ -62,14 +64,7 @@ function M.setup(spec, opts) | |||
| end | ||||
| 
 | ||||
| function M.stats() | ||||
|   local ret = { count = 0, loaded = 0 } | ||||
|   for _, plugin in pairs(require("lazy.core.config").plugins) do | ||||
|     ret.count = ret.count + 1 | ||||
|     if plugin._.loaded then | ||||
|       ret.loaded = ret.loaded + 1 | ||||
|     end | ||||
|   end | ||||
|   return ret | ||||
|   return require("lazy.stats").stats() | ||||
| end | ||||
| 
 | ||||
| function M.bootstrap() | ||||
|  |  | |||
							
								
								
									
										56
									
								
								lua/lazy/stats.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								lua/lazy/stats.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| local M = {} | ||||
| 
 | ||||
| ---@class LazyStats | ||||
| M._stats = { | ||||
|   -- startuptime in milliseconds till UIEnter | ||||
|   startuptime = 0, | ||||
|   -- when true, startuptime is the accurate cputime for the Neovim process. (Linux & Macos) | ||||
|   -- this is more accurate than `nvim --startuptime`, and as such will be slightly higher | ||||
|   -- when false, startuptime is calculated based on a delta with a timestamp when lazy started. | ||||
|   startuptime_cputime = false, | ||||
|   count = 0, -- total number of plugins | ||||
|   loaded = 0, -- number of loaded plugins | ||||
| } | ||||
| 
 | ||||
| function M.on_ui_enter() | ||||
|   if not M.C then | ||||
|     pcall(function() end) | ||||
|   end | ||||
| 
 | ||||
|   local ok = pcall(function() | ||||
|     local ffi = require("ffi") | ||||
|     ffi.cdef([[ | ||||
|         typedef long time_t; | ||||
|         typedef int clockid_t; | ||||
| 
 | ||||
|         typedef struct timespec { | ||||
|           time_t   tv_sec;        /* seconds */ | ||||
|           long     tv_nsec;       /* nanoseconds */ | ||||
|         } nanotime; | ||||
|         int clock_gettime(clockid_t clk_id, struct timespec *tp); | ||||
|       ]]) | ||||
|     local pnano = assert(ffi.new("nanotime[?]", 1)) | ||||
|     local CLOCK_PROCESS_CPUTIME_ID = jit.os == "OSX" and 12 or 2 | ||||
|     ffi.C.clock_gettime(CLOCK_PROCESS_CPUTIME_ID, pnano) | ||||
|     M._stats.startuptime = tonumber(pnano[0].tv_sec) / 1e6 + tonumber(pnano[0].tv_nsec) / 1e6 | ||||
|     M._stats.startuptime_cputime = true | ||||
|   end) | ||||
|   if not ok then | ||||
|     M._stats.startuptime = (vim.loop.hrtime() - require("lazy")._start) / 1e6 | ||||
|   end | ||||
|   vim.cmd([[do User LazyVimStarted]]) | ||||
| end | ||||
| 
 | ||||
| function M.stats() | ||||
|   M._stats.count = 0 | ||||
|   M._stats.loaded = 0 | ||||
|   for _, plugin in pairs(require("lazy.core.config").plugins) do | ||||
|     M._stats.count = M._stats.count + 1 | ||||
|     if plugin._.loaded then | ||||
|       M._stats.loaded = M._stats.loaded + 1 | ||||
|     end | ||||
|   end | ||||
|   return M._stats | ||||
| end | ||||
| 
 | ||||
| return M | ||||
|  | @ -491,6 +491,24 @@ function M:details(plugin) | |||
| end | ||||
| 
 | ||||
| function M:profile() | ||||
|   local stats = require("lazy.stats").stats() | ||||
|   local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100) | ||||
|   self:append("Startuptime: ", "LazyH2"):append(ms .. "ms", "Number"):nl():nl() | ||||
|   if stats.startuptime_cputime then | ||||
|     self:append("Based on the actual CPU time of the Neovim process till "):append("UIEnter", "LazySpecial") | ||||
|     self:append("."):nl() | ||||
|     self:append("This is more accurate than ") | ||||
|     self:append("`nvim --startuptime`", "@text.literal.markdown_inline") | ||||
|     self:append(".") | ||||
|   else | ||||
|     self:append("An accurate startuptime based on the actual CPU time of the Neovim process is not available."):nl() | ||||
|     self | ||||
|       :append("Startuptime is instead based on a delta with a timestamp when lazy started till ") | ||||
|       :append("UIEnter", "LazySpecial") | ||||
|     self:append(".") | ||||
|   end | ||||
|   self:nl():nl() | ||||
| 
 | ||||
|   self:append("Profile", "LazyH2"):nl():nl() | ||||
|   self | ||||
|     :append("You can press ") | ||||
|  | @ -505,6 +523,8 @@ function M:profile() | |||
| 
 | ||||
|   self:nl() | ||||
| 
 | ||||
|   self:nl():nl() | ||||
| 
 | ||||
|   ---@param a LazyProfile | ||||
|   ---@param b LazyProfile | ||||
|   local function sort(a, b) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue