diff options
author | Omer Strulovich <ostrulovich@fb.com> | 2022-03-28 20:09:36 -0700 |
---|---|---|
committer | Facebook GitHub Bot <facebook-github-bot@users.noreply.github.com> | 2022-03-28 20:09:36 -0700 |
commit | 6ea9e8f461853c32177f3a3bc0d2ae4ea5718452 (patch) | |
tree | 83478c3c6d466deb08aa9bcf89db1dcb6ee3d17c /core/src/main/java/com/facebook | |
parent | b11275d8fa0da92f8088e2f4a91285b734a77d84 (diff) | |
download | ktfmt-6ea9e8f461853c32177f3a3bc0d2ae4ea5718452.tar.gz |
Fix memory leak when creating KtFile
Summary:
The disposable is leaking, and according to this it's a known issue:
https://github.com/JetBrains/kotlin/blob/master/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt#L544
I could only find one thing through all the chaining:
https://github.com/JetBrains/kotlin/blob/master/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt#L149 -> clearing some cache
So instead of creating this environment per each file, causing a memory leak, we make one singleton item and ride it all the way to the end of the binary. While this item may grow in size, it seems to now do so, definitely not as the current memory leak.
See results of how faster the code is running on many files.
Reviewed By: hick209
Differential Revision: D35192326
fbshipit-source-id: 5308555bd689c18214ca2b824d28b8c283586572
Diffstat (limited to 'core/src/main/java/com/facebook')
-rw-r--r-- | core/src/main/java/com/facebook/ktfmt/format/Parser.kt | 55 |
1 files changed, 30 insertions, 25 deletions
diff --git a/core/src/main/java/com/facebook/ktfmt/format/Parser.kt b/core/src/main/java/com/facebook/ktfmt/format/Parser.kt index fa5a9c5..d8e4791 100644 --- a/core/src/main/java/com/facebook/ktfmt/format/Parser.kt +++ b/core/src/main/java/com/facebook/ktfmt/format/Parser.kt @@ -33,37 +33,42 @@ import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset /** Parser parses a Kotlin file given as a string and returns its parse tree. */ -open class Parser { - fun parse(code: String): KtFile { +object Parser { + + /** + * The environment used to open a KtFile + * + * We allocate it once, and ignore the Diposable. This causes a memory leak, but it was also + * causing a worse memory leak before when we created new ones and disposed them. This leak comes + * from [KotlinCoreEnvironment.createForProduction]: + * https://github.com/JetBrains/kotlin/blob/master/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt#L544 + */ + val env: KotlinCoreEnvironment + + init { + // To hide annoying warning on Windows + System.setProperty("idea.use.native.fs.for.win", "false") val disposable = Disposer.newDisposable() - try { - val configuration = CompilerConfiguration() - configuration.put( - CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, - PrintingMessageCollector(System.err, PLAIN_RELATIVE_PATHS, false)) - val env = - KotlinCoreEnvironment.createForProduction( - disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) - val virtualFile = LightVirtualFile("temp.kts", KotlinFileType.INSTANCE, code) - val ktFile = PsiManager.getInstance(env.project).findFile(virtualFile) as KtFile - ktFile.collectDescendantsOfType<PsiErrorElement>().let { - if (it.isNotEmpty()) throwParseError(code, it[0]) - } - return ktFile - } finally { - disposable.dispose() + val configuration = CompilerConfiguration() + configuration.put( + CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, + PrintingMessageCollector(System.err, PLAIN_RELATIVE_PATHS, false)) + env = + KotlinCoreEnvironment.createForProduction( + disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + } + + fun parse(code: String): KtFile { + val virtualFile = LightVirtualFile("temp.kts", KotlinFileType.INSTANCE, code) + val ktFile = PsiManager.getInstance(env.project).findFile(virtualFile) as KtFile + ktFile.collectDescendantsOfType<PsiErrorElement>().let { + if (it.isNotEmpty()) throwParseError(code, it[0]) } + return ktFile } private fun throwParseError(fileContents: String, error: PsiErrorElement): Nothing { throw ParseError( error.errorDescription, StringUtil.offsetToLineColumn(fileContents, error.startOffset)) } - - companion object : Parser() { - init { - // To hide annoying warning on Windows - System.setProperty("idea.use.native.fs.for.win", "false") - } - } } |