-
-
Notifications
You must be signed in to change notification settings - Fork 880
-
-
Notifications
You must be signed in to change notification settings - Fork 880
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
Slow tsx and typescript #1396
Comments
As you say in your issue description, it might be out of our reach. We'll try our best to enhance performances, but we can't guarantee anything. |
I'm just wondering if other people are still having this issue and if they have any workarounds for the time being. |
I think I do have this issue. Using treesitter highlighting makes things noticeably slower when both opening and moving around in a typescript file. |
Same here |
Hi, I think this might be related to the treesitter runtime update, can you check if compiling neovim with a previous version fix this issue? See neovim/neovim#14897 |
Can you check if #1442 resolves this? |
I updated Treesitter to the latest version, including #1442 , but sadly nothing's changed. |
@stsewd , apologies for the late response. I tried @clason 's solution from neovim/neovim#14897 which merged with And these typescript files I'm talking about are not crazy big files. I'm talking <100 lines of typescript. |
Can confirm I'm getting the same experience. My laptop is pretty fast so its not a big deal, but where JavaScript files in the same project are near instantaneous to load, there is a slight but definitely discernible delay in TS files when they are loaded. |
This was bothering me, as the delay can be quite annoying when switching between many buffers. I'm still fairly new to My assumption was that the highlights query should only need to be parsed once, and cached for every other buffer that will be opened, but it seems like that isn't the case. Swapping between buffers with After digging into If I change I don't know what the real solution should be, maybe |
@trixnz can you share this fix of yours? I don't personally have problems with lag switching buffers but it might be a clue in how to fix the general speed problem. Also, I believe one important aspect about this issue is that, at least in my experience, the speed of Treesitter varies between languages. From what I've observed, opening JavaScript and Lua files are incredibly fast, but Typescript and Python (the two languages I most frequently use) are terribly slow. This might be an issue on the language-specific implementations. Maybe the TypeScript and Python parsers are using some unnecessary laggy stuff. Is there anyone familiar to these parsers' development that can weigh in? |
@trixnz I dont' see that slow-down at all with |
Sure, but I wouldn't advise doing it this way. This was purely speculative changes to see where the bottleneck was. I believe this will break the moment you use more than one query, but as I was only working in a single .ts file with only diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 84b6a5f13..17ae14b6c 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -215,15 +215,18 @@ function TSHighlighter:on_changedtree(changes)
end
end
+-- Store built queries globally, rather than per TSHighlighter instance
+local _queries = {}
+
--- Gets the query used for @param lang
---
--- @param lang A language used by the highlighter.
function TSHighlighter:get_query(lang)
- if not self._queries[lang] then
- self._queries[lang] = TSHighlighterQuery.new(lang)
+ if not _queries[lang] then
+ _queries[lang] = TSHighlighterQuery.new(lang)
end
- return self._queries[lang]
+ return _queries[lang]
end
---@private
I've tried disabling all modules except for highlighting and couldn't get it to go any faster. However, I did find some interesting results when comparing the performance of the Note: At the time of writing, I used the latest master revisions of each grammar repo and
bench_nvim_treesitter.js
const Parser = require("tree-sitter");
const { Query } = Parser;
const TypeScript = require("tree-sitter-typescript");
const fs = require("fs");
const highlightsJs = Buffer.from(
fs
.readFileSync("/home/cam/.local/share/nvim/site/pack/paqs/start/nvim-treesitter/queries/ecma/highlights.scm")
.toString()
.replaceAll("vim-match", "match")
);
const highlightsTs = Buffer.from(
fs
.readFileSync("/home/cam/.local/share/nvim/site/pack/paqs/start/nvim-treesitter/queries/typescript/highlights.scm")
.toString()
.replaceAll("vim-match", "match")
);
const query = new Query(TypeScript.typescript, Buffer.concat([highlightsJs, highlightsTs])); bench_treesitter.js
const Parser = require("tree-sitter");
const { Query } = Parser;
const TypeScript = require("tree-sitter-typescript");
const fs = require("fs");
const highlightsJs = fs.readFileSync("./node_modules/tree-sitter-javascript/queries/highlights.scm");
const highlightsTs = fs.readFileSync("./node_modules/tree-sitter-typescript/queries/highlights.scm");
const query = new Query(TypeScript.typescript, Buffer.concat([highlightsJs, highlightsTs])); So while there are performance differences in the upstream grammer highlights vs those in this repo, it still takes a good amount of time to build the query in both cases. Almost all of that time can be found spent in ts_query__analyze_patterns. If Again, this codebase is new to me so I might be up the wrong tree entirely but just figured I'd throw some braindumps down in the hopes that it might help someone smarter than me :). |
I don't have any explicit settings set for treesitter folding and I have my foldmethod as marker. Do I need to explicitly disable folding? |
@trixnz I also saw that the queries for highlighting and injections don't get cached like out modules. Eventually, we should upstream our caching logic (we don't load folding/textobjects/indent queries twice) I saw that ts_query__analyze_patterns was causing problems, this seemed to be introduced by 0.19.X tree-sitter/tree-sitter#973 |
After a little bit more experimentation, I've come to a solution that solves my needs for the time being. I found that So, when my LSP attaches I warm up typescript/javascript queries by parsing them up and overriding them. Essentially i'm (ab)using the user overrides as a cache mechanism. Probably a good place for a cache for anyone brave enough to take it on 😄. Attached the prebuild snippet below for anyone who sees this as a reasonable hack: local TSPrebuild = {}
local has_prebuilt = false
TSPrebuild.on_attach = function(client, bufnr)
if has_prebuilt then return end
local query = require("vim.treesitter.query")
local function safe_read(filename, read_quantifier)
local file, err = io.open(filename, "r")
if not file then error(err) end
local content = file:read(read_quantifier)
io.close(file)
return content
end
local function read_query_files(filenames)
local contents = {}
for _, filename in ipairs(filenames) do table.insert(contents, safe_read(filename, "*a")) end
return table.concat(contents, "")
end
local function prebuild_query(lang, query_name)
local query_files = query.get_query_files(lang, query_name)
local query_string = read_query_files(query_files)
query.set_query(lang, query_name, query_string)
end
local prebuild_languages = {"typescript", "javascript", "tsx"}
for _, lang in ipairs(prebuild_languages) do
prebuild_query(lang, "highlights")
prebuild_query(lang, "injections")
end
has_prebuilt = true
end
return TSPrebuild |
We should really tackle the caching issue ASAP. I have time next weekend but if anyone has time it would be nice to port our caching system (or a better version) to Neovim core. So that highlight queries and injections don't get loaded multiple times. Anyone who has time now, please go ahead! ;-) |
@trixnz Would you mind sharing where in my configuration that snippet of code would go? |
It's really dependent on how your LSP is setup, but you just need to call |
I need it enable it to work with tree-sitter playground. Anyway, it works pretty well. Disabled typescript support for now. Waiting for this to be fixed. nvim-treesitter/nvim-treesitter#1396
Can someone confirm if this is still an issue? Closing in the meantime since there hasn't been any updates in some time. |
I think I still have it |
That sounds like a different issue (which is already opened). |
Still an issue in my case. Working on Debian, opening a .tsx file is impossibly slow and spikes CPU to 100% (and that with 300-line file). |
"Me too" comments without reproducible context (Neovim version, exact file) are useless. Performance is actively being worked on in Neovim core (not nvim-treesitter; there is nothing that can be done here except disable expensive query patterns and injections). |
Describe the bug
TSX and TypeScript files take a noticeably longer time to load than JavaScript files. I have looked at
--startuptime
and:profile
logs, and even when I delete all default regex-based syntax files loaded for TypeScript by NeoVim, treesitter is slow to load TS / TSX files.I saw on issues like #1082 , people are having the same issue as me. I've seen that it might be due to the newer versions of tree-sitter?
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Fast loading time, comparable to JSX files.
Output of
:checkhealth nvim_treesitter
Output of
nvim --version
Additional context
The text was updated successfully, but these errors were encountered: