Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

current_line_blame is too CPU intensive #877

Closed
WhyNotHugo opened this issue Sep 12, 2023 · 4 comments · Fixed by #878
Closed

current_line_blame is too CPU intensive #877

WhyNotHugo opened this issue Sep 12, 2023 · 4 comments · Fixed by #878
Labels
bug Something isn't working

Comments

@WhyNotHugo
Copy link
Contributor

WhyNotHugo commented Sep 12, 2023

Description

From what I'm understanding, current_line_blame runs an instance of git each time that the cursor moves to another line in order to extract blame information for the new line.

This is a problem for large repositories, where a single execution can spike CPU to 100% for a few seconds.

This becomes a terrible problem when scrolling; if I press j five times, then 5 git processes are spawned each one taking 100% of a CPU core. If I just hold j for a short while, this is what top looks like:

image

These can take around 20-30s to complete, given that they're all competing for CPU usage.

Neovim version

NVIM v0.9.1

Operating system and version

Linux 6.5.1-0-edge x86_64 Linux

Expected behavior

CPU usage should not spike due to blame calculation

Actual behavior

CPU usage spikes to 100% for each line change on large repositories.

Minimal config

for name, url in pairs{
  gitsigns = 'https://github.com/lewis6991/gitsigns.nvim',
  -- ADD OTHER PLUGINS _NECESSARY_ TO REPRODUCE THE ISSUE
} do
  local install_path = vim.fn.fnamemodify('gitsigns_issue/'..name, ':p')
  if vim.fn.isdirectory(install_path) == 0 then
    vim.fn.system { 'git', 'clone', '--depth=1', url, install_path }
  end
  vim.opt.runtimepath:append(install_path)
end

require("gitsigns").setup({
  current_line_blame = true,
  current_line_blame_opts = {
    delay = 0,
  },
})

Steps to reproduce

  1. git clone https://gitlab.alpinelinux.org/alpine/aports.git (or any other large repository)
  2. Open any file in the repository (e.g.: community/xdg-desktop-portal/APKBUILD)
  3. CPU will now spike once.
  4. Open top in another terminal
  5. Press j or k in neovim. Note how each keypress spawns a git process that takes a few seconds to exit.

Gitsigns debug messages

No response

@WhyNotHugo WhyNotHugo added the bug Something isn't working label Sep 12, 2023
@lewis6991
Copy link
Owner

To solve this we will need to kill unfinished git blame commands when the cursor moves.

@lewis6991
Copy link
Owner

@WhyNotHugo can you try #878.

It doesn't cancel any processes, but will prevent git blames from running concurrently.

lewis6991 added a commit that referenced this issue Sep 15, 2023
lewis6991 added a commit that referenced this issue Sep 15, 2023
lewis6991 added a commit that referenced this issue Sep 19, 2023
lewis6991 added a commit that referenced this issue Sep 19, 2023
lewis6991 added a commit that referenced this issue Sep 19, 2023
@WhyNotHugo
Copy link
Contributor Author

Given that git blame calculates blame for the whole file, can't its entire output be kept in memory? So when the cursor moves, the blame data can be read from memory, rather than running git blame which needs to do a lot of work.

@lewis6991
Copy link
Owner

Gitsigns doesn't fetch the blame for the entire file, it does it per line instead. I don't know if doing it for the entire file will be more efficient or not, but I would guess it wouldn't be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants