DEV Community

Cover image for Benchmarking SnaxVim's Startup Performance Against Popular Neovim Distros
glmlm
glmlm

Posted on

Benchmarking SnaxVim's Startup Performance Against Popular Neovim Distros

Fast startup is a small but important part of a pleasant Neovim experience. This benchmark examines how SnaxVim compares with several popular Neovim distros1 using multiple measurement methods.

For an overview of SnaxVim's design goals and philosophy, see the previous article: SnaxVim – A Minimal, Blazingly Fast Neovim Setup (Only 10 Plugins Included).

📋 1. Prerequisites

System Environment

  • Neovim Version: NVIM v0.12.5
  • OS / Kernel: Linux 6.18.52 x86_64 GNU/Linux
  • CPU: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  • Storage: Western Digital PC SN520 NVMe SSD 512GB
  • Benchmark Tools: hyperfine v1.20.0, vim-startuptime v1.3.2

Target Distros & Commit Hashes

Distro Name Repository Pinned Commit Core Configuration Repository2
SnaxVim SnaxVim/SnaxVim 81fc9f7 N/A
AstroNvim AstroNvim/template 49a7161 AstroNvim/AstroNvim (aa0545f)
kickstart.nvim nvim-lua/kickstart.nvim 80743df N/A
LazyVim LazyVim/starter 803bc18 LazyVim/LazyVim (9997009)
NvChad NvChad/starter e3572e1 NvChad/NvChad (add44b9), NvChad/ui (6ced113)

🚀 2. Methodology

Neovim startup measurements vary by tool because each approach uses a different measurement boundary. Although they often show similar broad trends, their absolute values are not directly interchangeable. Startup time is therefore measured using multiple methods to provide a multidimensional view of each Neovim distribution's startup performance.

Method A: External Process Lifecycle

Measures wall-clock time externally from process launch until the nvim +qa command exits. This includes Neovim initialization and exit processing, as well as effects from the operating system and execution environment.

hyperfine --min-runs 100 --warmup 10 \
"NVIM_APPNAME=SnaxVim nvim +qa" \
"NVIM_APPNAME=AstroNvim nvim +qa" \
"NVIM_APPNAME=kickstart.nvim nvim +qa" \
"NVIM_APPNAME=LazyVim nvim +qa" \
"NVIM_APPNAME=NvChad nvim +qa"
Enter fullscreen mode Exit fullscreen mode

Method B: Neovim Startup Timeline

Uses vim-startuptime, which repeatedly launches Neovim with its built-in --startuptime option. It focuses on initialization work recorded by Neovim and should not be interpreted as the complete wall-clock time until the editor is visibly ready.

for d in SnaxVim AstroNvim kickstart.nvim LazyVim NvChad; do \
  echo "=== $d ==="; \
  NVIM_APPNAME=$d vim-startuptime -vimpath nvim -count 100 -script | head -n 8 | grep "Total"; \
done
Enter fullscreen mode Exit fullscreen mode

Method C: Plugin Initialization to UI Readiness

Measures lazy.nvim's reported startup time. lazy.nvim calculates stats().startuptime up to the UIEnter event; the script waits for the subsequent LazyVimStarted user event and then records the already-calculated value. In this setup, the value is based on Neovim process CPU time rather than external wall-clock time.

for d in SnaxVim AstroNvim LazyVim NvChad; do \
  echo "=== $d ==="; \
  rm -f /tmp/lazy_runs.txt; \
  for i in {1..100}; do \
    NVIM_APPNAME=$d nvim -c "autocmd User LazyVimStarted lua local h, l = pcall(require, 'lazy'); local f = io.open('/tmp/lazy_runs.txt', 'a'); if f and h then f:write(tostring(l.stats().startuptime) .. '\n'); f:close() end; vim.cmd('qa')"; \
  done; \
  awk '{if(NR==1){min=$1;max=$1};sum+=$1;if($1>max)max=$1;if($1<min)min=$1} END {if(NR>0) printf "Total Average: %.6f msec\nTotal Max:     %.6f msec\nTotal Min:     %.6f msec\n", sum/NR, max, min; else print "Failed to capture."}' /tmp/lazy_runs.txt; \
done
Enter fullscreen mode Exit fullscreen mode

📊 3. Results

The chart below provides an overview of the startup performance measured by each benchmark. Lower values indicate faster startup.

The table below includes the measured averages and ranges for each benchmark.

Distro Method A
(hyperfine)
Method B
(vim-startuptime)
Method C
(lazy.nvim)
SnaxVim 21.8 ± 0.7 ms
20.1–24.2 ms
11.0 ms
10.4–12.4 ms
14.2 ms
12.9–18.6 ms
NvChad 24.1 ± 0.7 ms
22.9–29.4 ms
14.1 ms
13.3–15.6 ms
16.8 ms
15.7–21.4 ms
LazyVim 32.1 ± 2.5 ms
30.3–55.9 ms
20.7 ms
17.8–23.2 ms
26.6 ms
24.6–47.6 ms
AstroNvim 45.9 ± 2.6 ms
43.2–68.1 ms
36.7 ms
34.2–39.7 ms
43.3 ms
40.7–46.4 ms
kickstart.nvim 82.3 ± 1.8 ms
78.8–94.2 ms
59.6 ms
55.8–65.7 ms
N/A3

Raw benchmark output
$ hyperfine --min-runs 100 --warmup 10 \
"NVIM_APPNAME=SnaxVim nvim +qa" \
"NVIM_APPNAME=AstroNvim nvim +qa" \
"NVIM_APPNAME=kickstart.nvim nvim +qa" \
"NVIM_APPNAME=LazyVim nvim +qa" \
"NVIM_APPNAME=NvChad nvim +qa"
Benchmark 1: NVIM_APPNAME=SnaxVim nvim +qa
  Time (mean ± σ):      21.8 ms ±   0.7 ms    [User: 14.5 ms, System: 5.8 ms]
  Range (min … max):    20.1 ms …  24.2 ms    123 runs

Benchmark 2: NVIM_APPNAME=AstroNvim nvim +qa
  Time (mean ± σ):      45.9 ms ±   2.6 ms    [User: 33.0 ms, System: 10.1 ms]
  Range (min … max):    43.2 ms …  68.1 ms    100 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Benchmark 3: NVIM_APPNAME=kickstart.nvim nvim +qa
  Time (mean ± σ):      82.3 ms ±   1.8 ms    [User: 63.4 ms, System: 17.1 ms]
  Range (min … max):    78.8 ms …  94.2 ms    100 runs

Benchmark 4: NVIM_APPNAME=LazyVim nvim +qa
  Time (mean ± σ):      32.1 ms ±   2.5 ms    [User: 22.8 ms, System: 7.7 ms]
  Range (min … max):    30.3 ms …  55.9 ms    100 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Benchmark 5: NVIM_APPNAME=NvChad nvim +qa
  Time (mean ± σ):      24.1 ms ±   0.7 ms    [User: 16.2 ms, System: 6.3 ms]
  Range (min … max):    22.9 ms …  29.4 ms    109 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Summary
  NVIM_APPNAME=SnaxVim nvim +qa ran
    1.11 ± 0.05 times faster than NVIM_APPNAME=NvChad nvim +qa
    1.47 ± 0.13 times faster than NVIM_APPNAME=LazyVim nvim +qa
    2.11 ± 0.14 times faster than NVIM_APPNAME=AstroNvim nvim +qa
    3.78 ± 0.15 times faster than NVIM_APPNAME=kickstart.nvim nvim +qa
Enter fullscreen mode Exit fullscreen mode
$ for d in SnaxVim AstroNvim kickstart.nvim LazyVim NvChad; do \
  echo "=== $d ==="; \
  NVIM_APPNAME=$d vim-startuptime -vimpath nvim -count 100 -script | head -n 8 | grep "Total"; \
done
=== SnaxVim ===
Total Average: 10.951630 msec
Total Max:     12.351000 msec
Total Min:     10.382000 msec
=== AstroNvim ===
Total Average: 36.675830 msec
Total Max:     39.715000 msec
Total Min:     34.211000 msec
=== kickstart.nvim ===
Total Average: 59.649840 msec
Total Max:     65.697000 msec
Total Min:     55.834000 msec
=== LazyVim ===
Total Average: 20.696580 msec
Total Max:     23.166000 msec
Total Min:     17.756000 msec
=== NvChad ===
Total Average: 14.090530 msec
Total Max:     15.648000 msec
Total Min:     13.320000 msec
Enter fullscreen mode Exit fullscreen mode
$ for d in SnaxVim AstroNvim LazyVim NvChad; do \
  echo "=== $d ==="; \
  rm -f /tmp/lazy_runs.txt; \
  for i in {1..100}; do \
    NVIM_APPNAME=$d nvim -c "autocmd User LazyVimStarted lua local h, l = pcall(require, 'lazy'); local f = io.open('/tmp/lazy_runs.txt', 'a'); if f and h then f:write(tostri
ng(l.stats().startuptime) .. '\n'); f:close() end; vim.cmd('qa')"; \
  done; \
  awk '{if(NR==1){min=$1;max=$1};sum+=$1;if($1>max)max=$1;if($1<min)min=$1} END {if(NR>0) printf "Total Average: %.6f msec\nTotal Max:     %.6f msec\nTotal Min:     %.6f msec\n", sum/NR, max, min; else print "Failed to capture."}' /tmp/lazy_runs.txt; \
done
=== SnaxVim ===
Total Average: 14.243575 msec
Total Max:     18.558509 msec
Total Min:     12.912106 msec
=== AstroNvim ===
Total Average: 43.304165 msec
Total Max:     46.438125 msec
Total Min:     40.733614 msec
=== LazyVim ===
Total Average: 26.630609 msec
Total Max:     47.604416 msec
Total Min:     24.621206 msec
=== NvChad ===
Total Average: 16.785274 msec
Total Max:     21.369776 msec
Total Min:     15.704555 msec
Enter fullscreen mode Exit fullscreen mode

📝 4. Summary

SnaxVim was the fastest in all three benchmarks, outperforming every other distribution in each applicable measurement.
Its advantage over NvChad ranged from approximately 10% to 23%, depending on the measurement method.

LazyVim ranked third overall, while AstroNvim and kickstart.nvim recorded the highest startup times.
In the benchmarks that allowed a direct comparison, the ranking was consistent: SnaxVim was followed by NvChad, LazyVim, AstroNvim, and kickstart.nvim.

The three methods measure different parts of the startup process, so their absolute values should not be compared directly. However, the consistent results across the available measurements suggest that SnaxVim's performance was not specific to a single benchmarking approach.

If fast startup is important to your Neovim workflow, consider giving SnaxVim a try.

🔗 GitHub: https://github.com/SnaxVim/SnaxVim


  1. In this article, "Neovim distro" is used broadly to include preconfigured Neovim setups and starter templates. 

  2. "Core Configuration Repository" refers to the separate repository or repositories that provide the core configuration framework for a starter template. "N/A" indicates that the configuration is self-contained. 

  3. lazy.nvim startup statistics were not available for kickstart.nvim because it does not use lazy.nvim as its plugin manager. 

Top comments (0)