Skip to content

Commit 32fae63

Browse files
committed
fix: optimize parser performance by reusing parser instances
- Add global caches for parser instances and loaded languages - Reuse existing parser instances instead of creating new ones for each file - Cache loaded WASM language files to avoid redundant loading - This significantly reduces CPU usage during code indexing Fixes #7476
1 parent d1122ea commit 32fae63

File tree

1 file changed

+86
-58
lines changed

1 file changed

+86
-58
lines changed

src/services/tree-sitter/languageParser.ts

Lines changed: 86 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ async function loadLanguage(langName: string, sourceDirectory?: string) {
5252

5353
let isParserInitialized = false
5454

55+
// Global cache for parser instances to avoid recreating them
56+
const parserInstanceCache: Map<string, ParserT> = new Map()
57+
// Global cache for loaded languages to avoid reloading WASM files
58+
const languageCache: Map<string, LanguageT> = new Map()
59+
5560
/*
5661
Using node bindings for tree-sitter is problematic in vscode extensions
5762
because of incompatibility with electron. Going the .wasm route has the
@@ -96,134 +101,157 @@ export async function loadRequiredLanguageParsers(filesToParse: string[], source
96101
let query: QueryT
97102
let parserKey = ext // Default to using extension as key
98103

104+
// Determine the language name for caching
105+
let languageName: string
106+
let queryString: string
107+
99108
switch (ext) {
100109
case "js":
101110
case "jsx":
102111
case "json":
103-
language = await loadLanguage("javascript", sourceDirectory)
104-
query = new Query(language, javascriptQuery)
112+
languageName = "javascript"
113+
queryString = javascriptQuery
105114
break
106115
case "ts":
107-
language = await loadLanguage("typescript", sourceDirectory)
108-
query = new Query(language, typescriptQuery)
116+
languageName = "typescript"
117+
queryString = typescriptQuery
109118
break
110119
case "tsx":
111-
language = await loadLanguage("tsx", sourceDirectory)
112-
query = new Query(language, tsxQuery)
120+
languageName = "tsx"
121+
queryString = tsxQuery
113122
break
114123
case "py":
115-
language = await loadLanguage("python", sourceDirectory)
116-
query = new Query(language, pythonQuery)
124+
languageName = "python"
125+
queryString = pythonQuery
117126
break
118127
case "rs":
119-
language = await loadLanguage("rust", sourceDirectory)
120-
query = new Query(language, rustQuery)
128+
languageName = "rust"
129+
queryString = rustQuery
121130
break
122131
case "go":
123-
language = await loadLanguage("go", sourceDirectory)
124-
query = new Query(language, goQuery)
132+
languageName = "go"
133+
queryString = goQuery
125134
break
126135
case "cpp":
127136
case "hpp":
128-
language = await loadLanguage("cpp", sourceDirectory)
129-
query = new Query(language, cppQuery)
137+
languageName = "cpp"
138+
queryString = cppQuery
130139
break
131140
case "c":
132141
case "h":
133-
language = await loadLanguage("c", sourceDirectory)
134-
query = new Query(language, cQuery)
142+
languageName = "c"
143+
queryString = cQuery
135144
break
136145
case "cs":
137-
language = await loadLanguage("c_sharp", sourceDirectory)
138-
query = new Query(language, csharpQuery)
146+
languageName = "c_sharp"
147+
queryString = csharpQuery
139148
break
140149
case "rb":
141-
language = await loadLanguage("ruby", sourceDirectory)
142-
query = new Query(language, rubyQuery)
150+
languageName = "ruby"
151+
queryString = rubyQuery
143152
break
144153
case "java":
145-
language = await loadLanguage("java", sourceDirectory)
146-
query = new Query(language, javaQuery)
154+
languageName = "java"
155+
queryString = javaQuery
147156
break
148157
case "php":
149-
language = await loadLanguage("php", sourceDirectory)
150-
query = new Query(language, phpQuery)
158+
languageName = "php"
159+
queryString = phpQuery
151160
break
152161
case "swift":
153-
language = await loadLanguage("swift", sourceDirectory)
154-
query = new Query(language, swiftQuery)
162+
languageName = "swift"
163+
queryString = swiftQuery
155164
break
156165
case "kt":
157166
case "kts":
158-
language = await loadLanguage("kotlin", sourceDirectory)
159-
query = new Query(language, kotlinQuery)
167+
languageName = "kotlin"
168+
queryString = kotlinQuery
160169
break
161170
case "css":
162-
language = await loadLanguage("css", sourceDirectory)
163-
query = new Query(language, cssQuery)
171+
languageName = "css"
172+
queryString = cssQuery
164173
break
165174
case "html":
166-
language = await loadLanguage("html", sourceDirectory)
167-
query = new Query(language, htmlQuery)
175+
languageName = "html"
176+
queryString = htmlQuery
168177
break
169178
case "ml":
170179
case "mli":
171-
language = await loadLanguage("ocaml", sourceDirectory)
172-
query = new Query(language, ocamlQuery)
180+
languageName = "ocaml"
181+
queryString = ocamlQuery
173182
break
174183
case "scala":
175-
language = await loadLanguage("scala", sourceDirectory)
176-
query = new Query(language, luaQuery) // Temporarily use Lua query until Scala is implemented
184+
languageName = "scala"
185+
queryString = luaQuery // Temporarily use Lua query until Scala is implemented
177186
break
178187
case "sol":
179-
language = await loadLanguage("solidity", sourceDirectory)
180-
query = new Query(language, solidityQuery)
188+
languageName = "solidity"
189+
queryString = solidityQuery
181190
break
182191
case "toml":
183-
language = await loadLanguage("toml", sourceDirectory)
184-
query = new Query(language, tomlQuery)
192+
languageName = "toml"
193+
queryString = tomlQuery
185194
break
186195
case "vue":
187-
language = await loadLanguage("vue", sourceDirectory)
188-
query = new Query(language, vueQuery)
196+
languageName = "vue"
197+
queryString = vueQuery
189198
break
190199
case "lua":
191-
language = await loadLanguage("lua", sourceDirectory)
192-
query = new Query(language, luaQuery)
200+
languageName = "lua"
201+
queryString = luaQuery
193202
break
194203
case "rdl":
195-
language = await loadLanguage("systemrdl", sourceDirectory)
196-
query = new Query(language, systemrdlQuery)
204+
languageName = "systemrdl"
205+
queryString = systemrdlQuery
197206
break
198207
case "tla":
199-
language = await loadLanguage("tlaplus", sourceDirectory)
200-
query = new Query(language, tlaPlusQuery)
208+
languageName = "tlaplus"
209+
queryString = tlaPlusQuery
201210
break
202211
case "zig":
203-
language = await loadLanguage("zig", sourceDirectory)
204-
query = new Query(language, zigQuery)
212+
languageName = "zig"
213+
queryString = zigQuery
205214
break
206215
case "ejs":
207216
case "erb":
208217
parserKey = "embedded_template" // Use same key for both extensions.
209-
language = await loadLanguage("embedded_template", sourceDirectory)
210-
query = new Query(language, embeddedTemplateQuery)
218+
languageName = "embedded_template"
219+
queryString = embeddedTemplateQuery
211220
break
212221
case "el":
213-
language = await loadLanguage("elisp", sourceDirectory)
214-
query = new Query(language, elispQuery)
222+
languageName = "elisp"
223+
queryString = elispQuery
215224
break
216225
case "ex":
217226
case "exs":
218-
language = await loadLanguage("elixir", sourceDirectory)
219-
query = new Query(language, elixirQuery)
227+
languageName = "elixir"
228+
queryString = elixirQuery
220229
break
221230
default:
222231
throw new Error(`Unsupported language: ${ext}`)
223232
}
224233

225-
const parser = new Parser()
226-
parser.setLanguage(language)
234+
// Load language from cache or load it fresh
235+
if (languageCache.has(languageName)) {
236+
language = languageCache.get(languageName)!
237+
} else {
238+
language = await loadLanguage(languageName, sourceDirectory)
239+
languageCache.set(languageName, language)
240+
}
241+
242+
// Create query
243+
query = new Query(language, queryString)
244+
245+
// Reuse parser instance from cache or create new one
246+
let parser: ParserT
247+
if (parserInstanceCache.has(languageName)) {
248+
parser = parserInstanceCache.get(languageName)!
249+
} else {
250+
parser = new Parser()
251+
parser.setLanguage(language)
252+
parserInstanceCache.set(languageName, parser)
253+
}
254+
227255
parsers[parserKey] = { parser, query }
228256
}
229257

0 commit comments

Comments
 (0)