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

Performance - TTFI for Reopening Previously Imported Java Projects in VS Code #3852

Open
mamilic opened this issue Nov 10, 2024 · 8 comments

Comments

@mamilic
Copy link

mamilic commented Nov 10, 2024

I really appreciate all the effort put into supporting Java in VS Code. I was wondering if there are any improvements that could be made to enhance the time to first interaction (TTFI) when reopening projects that have already been imported, rather than on the initial import?

@mamilic
Copy link
Author

mamilic commented Nov 14, 2024

Hi @rgrunber,

Really appreciate your willing to explain and interact. Thanks for that!

This is my understadning, as far as I can tell the import process consists of 2 steaps.

  1. Importing Maven/Gradle Project, https://github.com/eclipse-jdtls/eclipse.jdt.ls/blob/f155e1fc90618b558899c3722606feccfc89e210/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java#L219-L243, though it might be that it is always executed due to this at least for gradle, https://docs.gradle.org/current/userguide/configuration_cache.html?
  2. Code Indexing, https://github.com/eclipse-jdtls/eclipse.jdt.ls/blob/master/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java#L326

Is there any steps that can be improved here, as I see that these 2 steps are always fully executed, regardless whether the project has already been imported. Though, there might be more steps, please do correct me.

@rgrunber
Copy link
Member

rgrunber commented Nov 14, 2024

We often come back to looking at ways of improving startup times. There are basically 3-ish phases of going from the moment a project is opened in the workspace, to having vscode-java be fully ready to interact with it. I'll use JDT-LS itself as an example when importing from scratch since it's larger. (It should be noted that there are certain interactions you can perform even while certain operations are still happening) :

  1. the language server needs to be brought up, as it is an OSGi (Eclipse) application with a lot of different dependencies. This is usually independent of the project. (eg. for JDT-LS this takes a few seconds at most)
  2. the language server begins the project import, which is mostly about generating/discovering the necessary metadata about the project. (eg. for JDT-LS project this takes about 1 minute). I think this takes so long because a good amount of time is spent downloading the dependencies.
  3. the project gets built (eg. for JDT-LS project this takes about 30 seconds)

If you take a project that has never been imported, or run Java: Clean Java Language Server Workspace from the command palette, it should always take longer than if you imported a project that you already imported. We definitely avoid rebuilding a project if we detect it has already been done, and so the language server merely tries to import it, which takes a much shorter time.

If I just re-load the VS Code window (as if I just re-opened the JDT-LS project), it takes about 4 seconds for the project import and another 3 seconds for the build phase. In other words, much quicker.

One of the improvements to indexing we made was java.sharedIndexes.enabled (defaults to auto, so only enabled in VS Code Insiders) & java.sharedIndexes.location. These index all libraries in a common location, and since dependencies can overlap locally, it saves time on avoiding the need to rebuild the same library (eg JDK 21) for each project. With that said, the indexing happens in parallel, and doesn't actually contribute to import/build time. If you didn't have the index, you'd still get errors/warnings and I'm pretty sure completion would still work. Just that certain search operations would block until indexing was complete. So it doesn't really contribute to import time.

Update: I tried with https://github.com/spring-projects/spring-petclinic (imported through Gradle build metadata) and observed about the same. Took about 40s to initialize/import and another 30s to build. Reloading the project took about 3s and an additional 6s for the build. If you really wanted to cut down on time, I guess you could try disabling the autobuild (java.autobuild.enabled: false).

@mamilic
Copy link
Author

mamilic commented Nov 14, 2024

@rgrunber , thank you for explanation! I've tried the peclinic as well and the results are.
With Shared indices/indexes turned on, and auto build is disabled. I was wondering if there are some setting to adjust to get your results? 😄

This is run on Arch Linux,
Lenovo ThinkPad L14 Gen 1
40.0 GiB RAM
AMD Ryzen™ 5 PRO 4650U with Radeon™ Graphics × 12

Import

!ENTRY org.eclipse.jdt.ls.core 1 0 2024-11-14 16:31:16.502
!MESSAGE Workspace initialized in 46473ms

Reload/Reopen

!ENTRY org.eclipse.jdt.ls.core 1 0 2024-11-14 16:32:08.987
!MESSAGE Workspace initialized in 22568ms

@rgrunber
Copy link
Member

I would think you should be getting better performance than me. I've only got a Dell Inc. XPS 13 9370, Intel® Core™ i7-8650U × 8, with 16 GiB RAM on Fedora 40.

Are you able to share what the full language server logs look like from reload to finishing ? You could also add "java.trace.server": "verbose" to your setting to get more information. I noticed that the Gradle daemon remains up as a background process even when I close the project, and if I terminate that process, it does add some time to the import, but only about 6s extra, which doesn't account for what you're seeing.

@mamilic
Copy link
Author

mamilic commented Nov 14, 2024

@rgrunber , I run with verbose enabled, jdtls.log
But have no clue where to look at. :/

@rgrunber
Copy link
Member

rgrunber commented Nov 14, 2024

I'm seeing the exact same thing now that I started using the vscode-gradle extension (in combination with vscode-java). Note that JDT-LS has an embedded Gradle build support, but I believe for correctness the Gradle build server (which integrates with vscode-java) can be better, along with more overall support for other Gradle features.

Using this basic setup, on spring-petclinic, I think a full build took about 1min while a simple reload took around 30s. That's probably closer to what you're seeing. I tried with "gradle.allowParallelRun": true but maybe that improved things for the initial build.

@jdneo , is the Gradle build server likely to be a bit slower than Buildship in project import ?

@mamilic
Copy link
Author

mamilic commented Nov 15, 2024

@rgrunber , what are differences between buildship and vscode-gradle? I've noticed that buildship outputs the build files into the "bin" folder, and plain gradle build outputs to "build" folder. Also, the structure of those is different. Is there a way to setup buildship to behave as plain gradle?

@rgrunber
Copy link
Member

#3260 (comment)

In short, the new approach will delegate the build job to Gradle.

I think using vscode-gradle is just closer to the expected output from commandline. T[the 'bin' folder issue is also mentioned as something vscode-gradle resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants