redhat-developer / vscode-java

Java Language Support for Visual Studio Code
Eclipse Public License 2.0
2.07k stars 429 forks source link

Whole project recompiles with each keystroke #1765

Open xster opened 3 years ago

xster commented 3 years ago

Sometime between version 0.64.1 and now, the build triggering behavior seems to have changed. Whereas changes within a file still produced a reasonably fast auto-complete, it seems like each keystroke now triggers a rebuild of the entire project including the edited file, other files in the project and all declared Java dependencies. This seems to generally make auto-complete unusable since one is likely typing around the time auto-complete is needed and if each keystroke triggers a 1 minute build, auto-complete is generally always loading.

Perhaps it's possible to restrict the rebuilding to the edited file, or cache all the symbols from the previous build until the next build is ready?

Environment
Additional Informations

When I start typing, it triggers the below in the Java Build Status pane. Each build takes a few minutes.

8394ded0 Building [Done]
ba7e2d19 Validate documents [Done]
00cd587d Publish Diagnostics [Done]
c9fb754c Building [Done]
467b8d20 Building [Done]
a25e99a1 Validate documents [Done]
411b4544 Publish Diagnostics [Done]
c1bd89da Building [Done]
240f6be2 Building [Done]
a3536bca Building [Done]
6cea6ad2 Building [Done]
testforstephen commented 3 years ago

Duplicated with https://github.com/redhat-developer/vscode-java/issues/996

The "Building" message you saw in the status panel is just a fake message, not representing a compilation operation.

testforstephen commented 3 years ago

Java extension version: 0.64.1

Your Java extension version is a little old, could you update all Java extensions to the latest version and try again?

AFAIK, the side Java extensions such as Java test runner pushed a bunch of performance improvement against the auto completion performance in the past few months.

BTW, do you enable file auto save? the file save is probably triggering the auto build job.

xster commented 3 years ago

Thanks.

File auto save is off. I'm trying now on 0.73.0 with Java 11. Same symptom. I think the "building" messages are actually doing something, since each of them breaks down (while running) into a building 123/1000 files message.

deekshithanand commented 3 years ago

I can confirm this issue for me. Each keystroke causes the circular arrow to rotate and I get similar messages like shared above. I had disabled java autobuild and auto save was disabled by default for me

dbarvitsky commented 2 years ago

The "Publish Diagnostics" takes the longest for me. I frequently see java processes (2 of them because of the hybrid mode) in the background hugging the CPU (200-300% spikes), notably after the change to a Java file is made. It slows down the intellisence, and one has to wait for good 10-30 seconds for the auto-completion hints to appear. I attempted the following:

If I can make a suggestion:

kkilictepe commented 2 years ago

Same here. Intellisense performance is terrible. Any update?

DrewCCannedy commented 1 year ago

Same issue, would love an update.

snjeza commented 1 year ago

@DrewCCannedy @kkilictepe @dbarvitsky @deekshithanand @xster Could you provide a project example reproducing the issue?

kkilictepe commented 1 year ago

@snjeza I cant share as I am working on a commercial project.Anything else (logs etc?) that I can provide but the project codes itself? My project is huge, with a lot of internal dependencies.

d3milord commented 1 year ago

I actually found out what could be the issue. I started with the same problem as described by @xster with a cyclic Building,Validate,Publish routine at each keystroke.

After I've searched for build in the full settings page, I found that the extension "Language Support for Java(TM) by Red Hat" (ID: redhat.java) has a setting named "Java > Autobuild: Enabled" ("java.autobuild.enabled") set at True by default. It triggers (as the name says) an automatic build after some event (code/text changes). After I disabled it the automatic fire of the build has stopped. It only keeps doing the "Validating" step at each keystroke and sometimes the "Publish" one.

Probably the Validating step is controlled by the intellisense to validate the code at each change. It could be made after a delay, but for me it's not impacting the performance a lot as the Build step.

Intellisense speeded up even in complex legacy projects and it seems the entire usability has improved. Actually I'm still trying to find out what are the downsides of haing disabled that autobuild.

Let me know if you know something about that feature.

snjeza commented 1 year ago

@d3milord If you set java.autobuild.enabled=true , Java LS will build your workspace only when you save a file. Could you show your settings.json?

d3milord commented 1 year ago
{
    "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx1G -Xms100m -javaagent:\"c:\\Users\\davidepecorari\\.vscode\\extensions\\gabrielbb.vscode-lombok-1.0.1\\server\\lombok.jar\"",
    "files.exclude": {
        "**/.classpath": true,
        "**/.project": true,
        "**/.settings": true,
        "**/.factorypath": true
    },
    "redhat.telemetry.enabled": false,
    "editor.suggestSelection": "first",
    "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
    "git.confirmSync": false,
    "git.enableSmartCommit": true,
    "java.configuration.runtimes": [
        {
          "name": "JavaSE-1.8",
          "path": "C:\\Program Files\\Java\\jdk1.8.0_202",
        },
        {
          "name": "JavaSE-11",
          "path": "C:\\Program Files\\Java\\jdk-11.0.13",
          "default": true
        }
    ],
    "java.referencesCodeLens.enabled": true,
    "java.debug.settings.showHex": true,
    "json.schemas": [],
    "workbench.startupEditor": "none",
    "workbench.colorCustomizations": {},
    "java.inlayHints.parameterNames.enabled": "none",
    "workbench.editor.enablePreviewFromQuickOpen": true,
    "workbench.editor.enablePreview": false,
    "java.debug.settings.enableRunDebugCodeLens": false,
    "java.help.showReleaseNotes": false,
    "java.autobuild.enabled": false,
    "maven.dependency.enableConflictDiagnostics": false,
    "javascript.suggestionActions.enabled": false,
    "typescript.suggestionActions.enabled": false
}
snjeza commented 1 year ago

@d3milord could you remove the gabrielbb.vscode-lombok extension and update java.jdt.ls.vmargs to

 "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx4G -Xms100m ",

See Lombok Support

francescodedomenico commented 1 year ago

I can confirm this is happening to me on a large enterprise Java Project with hundreds of classes (sometimes large ones too, 6000+ lines of code). It's a Spring Boot Gradle Project, and I got the message that the language server got out of memory.

When I do get an Intellisense suggestion it comes with a 20 seconds delay (when lucky), often it shows no popup at all, making it hardly usable.

The curious thing here is how fast is Language Server for Java by Netbeans instead, while it doesn't have the features I need the code suggestion are almost instantly provided.

I did my tests on a brand new vscode installation with vscode-java only enabled as extension.

iamfreeman commented 1 year ago

I have the same issue here. I am working on a large project with hundreds of classes. Right now anytime I make a keystroke, "Publish Diagnostics" tasks take me 5s to complete and the intellisense popup triggered after that. That makes me wait for at least 5s to get my intellisense shown up. It is a disaster when I doing my implementation. I do not want to swtich to IntelliJ but if the speed is that slow I have no choice

https://user-images.githubusercontent.com/4750762/215580386-a5a0bea0-eafa-4650-a124-a59bb66ff900.mp4

snjeza commented 1 year ago

@iamfreeman Could you attach your server log? - Enable logging

iamfreeman commented 1 year ago

@snjeza, not a problem. I have attached the server log at the time I hit "v" key as shown in my previous video.

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:47.273 !MESSAGE >> document/codeAction

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:47.393 !MESSAGE >> textDocument/inlayHint

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:47.467 !MESSAGE >> document/codeAction

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:47.513 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:48.232 !MESSAGE >> document/foldingRange

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:48.501 !MESSAGE >> document/didChange

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:48.509 !MESSAGE >> document/completion

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:48.517 !MESSAGE Reconciled 1. Took 4 ms

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.825 !MESSAGE Completion request completed

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.838 !MESSAGE >> document/codeAction

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.839 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.839 !MESSAGE >> document/documentSymbol

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.839 !MESSAGE >> document/foldingRange

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.840 !MESSAGE >> textDocument/semanticTokens/full

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.840 !MESSAGE >> textDocument/inlayHint

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.869 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:53.884 !MESSAGE >> document/resolveCompletionItem

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:54.251 !MESSAGE begin problem for /TblVendorService.java

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:54.251 !MESSAGE 3 problems reported for /TblVendorService.java

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:54.252 !MESSAGE Validated 1. Took 5324 ms

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 12:27:54.513 !MESSAGE >> document/codeAction

snjeza commented 1 year ago

I have attached the server log at the time I hit "v" key as shown in my previous video.

Could you set

"java.trace.server": "verbose",

and repeat the log?

iamfreeman commented 1 year ago

This is the setting for my user workspace, I use this setting to generate my previous log:

{
    "java.codeGeneration.generateComments": true,
    "security.workspace.trust.untrustedFiles": "open",
    "java.eclipse.downloadSources": true,
    "java.import.exclusions": [

        "**/node_modules/**",
        "**/.metadata/**",
        "**/archetype-resources/**",
        "**/META-INF/maven/**"
    ],
    "java.maxConcurrentBuilds": 2,
    "java.showBuildStatusOnStart.enabled": "notification",
    "java.trace.server": "verbose",
    "java.typeHierarchy.lazyLoad": true,
    "javascript.updateImportsOnFileMove.enabled": "always"
}

This is the setting for my project, this time, I add the : "java.trace.server": "verbose", to my project setting as well:

{
    "java.configuration.updateBuildConfiguration": "automatic",
    "sqltools.connections": [
        {
            "mysqlOptions": {
                "authProtocol": "default"
            },
            "previewLimit": 50,
            "server": "localhost",
            "port": 3306,
            "driver": "MySQL",
            "name": "root-local",
            "database": "xxxxx",
            "username": "xxxx",
            "password": "xxxx"
        }
    ],
    "java.trace.server": "verbose",
    "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx4G -Xms1G -Xlog:disable"
}

I got the pretty much the same result from the server log:

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:02.306 !MESSAGE >> document/codeAction

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:02.570 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:02.898 !MESSAGE >> textDocument/inlayHint

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:02.983 !MESSAGE >> document/didChange

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:02.988 !MESSAGE >> document/completion

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:03.003 !MESSAGE Reconciled 1. Took 7 ms

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.044 !MESSAGE Completion request completed

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.052 !MESSAGE >> document/codeAction

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.053 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.054 !MESSAGE >> document/documentSymbol

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.054 !MESSAGE >> textDocument/inlayHint

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.054 !MESSAGE >> document/foldingRange

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.054 !MESSAGE >> textDocument/semanticTokens/full

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.092 !MESSAGE >> document/resolveCompletionItem

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.309 !MESSAGE >> workspace/executeCommand vscode.java.resolveMainMethod

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.619 !MESSAGE begin problem for /TblVendorService.java

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.620 !MESSAGE 3 problems reported for /TblVendorService.java

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.620 !MESSAGE Validated 1. Took 5216 ms

!ENTRY org.eclipse.jdt.ls.core 1 0 2023-01-30 13:21:08.886 !MESSAGE >> document/codeAction

@snjeza , Did I miss something?

snjeza commented 1 year ago

Did I miss something?

@xster Could you check your .vscode/settings.json?

snjeza commented 1 year ago

@xster Could you also try to set

"java.completion.maxResults": 50,
iamfreeman commented 1 year ago

Hi @snjeza , same result, no difference. I also tried on my my colleague's workstation, still, the same result. I relaunch VSCode and tried again. Same result

snjeza commented 1 year ago

I got the pretty much the same result from the server log:

Could you try to clean the workspace directory:

francescodedomenico commented 1 year ago

Currently this is happening to me on a @Service Spring java class with 6700+ lines of code and lots of imports and @Autowired.

On smaller classes the build step is fast enough to provide intellicode suggestions.

In this particular one the "Publish Diagnostics" step is very slow and usually results in several loops after each "dot" pressed after a local variable eg: iAmAVariable. (expected intellisense popup here)

af9f56d5 Validate documents [Done] fc5b1b21 Publish Diagnostics [Done] 13e3c4a4 Validate documents [Done] af8bbb62 Publish Diagnostics [Done] a5b94203 Validate documents [Done] 08467232 Publish Diagnostics [Done] 4c3aed8f Validate documents [Done] 48130557 Validate documents [Done] c810c682 Validate documents [Done] 5f310a3d Validate documents [Done] 3609b0b3 Publish Diagnostics [Done] b8b61fed Validate documents [Done] 6843baf8 Publish Diagnostics: 25% [250/1000]

edit: I did produce a video showing the effect on the main class of the project, I made a simple pojo class SomeClass

public class SomeClass {
    String someField;

    public SomeClass(String field){
        this.someField = field;
    }

    public String getSomeField() {
        return someField;
    }

    public void setSomeField(String someField) {
        this.someField = someField;
    }
}

Then I made a new void method to construct the new class, trying to fetch any of the getter of setter method inside, and this is the result

https://user-images.githubusercontent.com/1148689/215729955-ed48fef6-d2b6-4908-8311-b7d1c243830f.mp4

This project has been fully developed with vscode and vscode-java with Spring tools one year ago. When I did open it again with a updated vscode it felt like unusable and that's why I started collecting these evidences using a brand new vscode installation.

Other coworkers did clone the same repository and facing the same lag.

fbricon commented 1 year ago

@francescodedomenico do you see this issue when downgrading to 1.13 ? Is it a Maven project, invoking some plugins to process/generate resources?

francescodedomenico commented 1 year ago

@fbricon hi! it's a Gradle project, at the beginning of the project Gradle sync is performed, but that's it, after the initial synchronization I only see the Java build spinning and looping over.

About code generation plugins there is lombok, since the last versions of vscode-java I did disable the dedicated vscode lombok extenion in order to use the one provided by vscode-java. (however the test is performed on a brand new installation where the lombok extension has never been installed so there is no java agent in settings.json)

I tried to downgrade to 1.13 and the situation is slightly better, I can obtain a suggestion after 15-20 seconds and only after deleting and rewriting the whole variable name followed by ".", sometimes I got the suggestion by deleting and rewriting the dot "."

In 1.14 the variable statement results into an unsuccessful java build caused by the unfinished statement itself (the one I'm waiting intellisense to trigger), deleting and rewriting the variable, deleting and rewriting the dot, won't help with intellisense.

testforstephen commented 1 year ago

Looks like Java extension is having performance while editing a larger file. Can anyone share the CPU profiling result of Java language server extension?

Here are some steps to profile Java language server extension:

image

francescodedomenico commented 1 year ago

@testforstephen here's a snapshot of an execution of my own, the profiling stopped curiously when the process ended (and of course I wasn't expecting it to end since vscode and the java project was still opened)

edit: I added a second snapshot showcasing the increasingly number of invocations by publish diagnostics loop

snapshot-1675177368102.zip snapshot-1675178952400.zip

iamfreeman commented 1 year ago

@snjeza, I cleared my workspace and tried again, same result.

@testforstephen , my project is a maven project which build comptely from scratch by VScode. similar as @francescodedomenico mentioned, when the project size is small, the intellisense made a good performance. However, as more and more lines of codes coming in, the performance dropped dramatically.

I do have some files with 5000+ lines of codes, but the file in video I shared previously only contains 600 lines of codes

@testforstephen , I have also attached my snapshot of an execution of my project. vscode-cpu-snapshot-20230131155823.zip

testforstephen commented 1 year ago

Thank you for sharing the snapshots.

@iamfreeman In your profiling snapshot, I see lombok calls took much CPU time. Could you try to disable the setting java.jdt.ls.lombokSupport.enabled to turn off lombok agent? It requires VS Code reload to take effect.

image

testforstephen commented 1 year ago

@testforstephen here's a snapshot of an execution of my own, the profiling stopped curiously when the process ended (and of course I wasn't expecting it to end since vscode and the java project was still opened)

edit: I added a second snapshot showcasing the increasingly number of invocations by publish diagnostics loop

snapshot-1675177368102.zip snapshot-1675178952400.zip

@francescodedomenico thank you for providing the snapshots. I see the Indexing job is busy finding imports, and the Diagnostic job is busy compiling the AST. Did you enable "Auto Save" feature in VS Code? File save could trigger compilation and indexing jobs.

francescodedomenico commented 1 year ago

You welcome @testforstephen I do not have autosave enabled, since it's a fairly brand new installation I can share you the vscode settings.json for global settings and workspace:

{
    "java.autobuild.enabled": false,
    "workbench.colorTheme": "One Dark Pro",
    "editor.minimap.enabled": false,
    "boot-java.rewrite.reconcile": true,
    "git.autofetch": true,
    "files.exclude": {
        "**/.classpath": true,
        "**/.project": true,
        "**/.settings": true,
        "**/.factorypath": true
    }
}

and this is the workspace settings.json

{
    "java.compile.nullAnalysis.mode": "automatic",
    "java.configuration.updateBuildConfiguration": "automatic",
    "java.autobuild.enabled": false,
    "java.progressReports.enabled": true,
    "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx12G -Xms100m -Xlog:disable",
    "java.trace.server": "verbose",
    "java.completion.maxResults": 50,
    "java.import.gradle.java.home": "C:/Program Files/Eclipse Adoptium/jdk-11.0.17.8-hotspot"
}

please let me know if you think there's something worth changing

iamfreeman commented 1 year ago

@testforstephen , after I disable the lombok support, the performance improved a lot. However, I do need lombok support. Is there any workaround?

Currently I am using version 1.18.22

testforstephen commented 1 year ago

@testforstephen , after I disable the lombok support, the performance improved a lot. However, I do need lombok support. Is there any workaround?

Currently I am using version 1.18.22

The Lombok code is from Lombok project, I didn't have an immediate answer here. Ultimately we need to work with Lombok team to figure out the root cause.

@iamfreeman Could you share which Lombok features you used in your sample? It's better to provide a sample class to help us to analyze the issue further.

iamfreeman commented 1 year ago

Not a problem:

This is a typical DTO we are using with lombok

import java.util.List;
import com.emonster.saleserp.domain.enumeration.Currency;
import com.emonster.saleserp.domain.enumeration.LeadTimeType;
import com.emonster.saleserp.domain.enumeration.PriceDataSource;
import com.emonster.saleserp.domain.enumeration.VendorType;
import java.util.Objects;

import javax.persistence.Lob;
import javax.validation.constraints.NotNull;

import com.emonster.saleserp.jsonView.CommonView;
import com.fasterxml.jackson.annotation.JsonView;

import lombok.Data;

/**
 * A DTO for the {@link com.emonster.saleserp.domain.TblVendor} entity.
 */
@Data
public class TblVendorDTO extends AbstractAuditingDTO {

    @JsonView(CommonView.PublicView.class)
    private Long id;

    @NotNull
    @JsonView(CommonView.PublicView.class)
    private String name;

    @JsonView(CommonView.PublicView.class)
    private Long externalId;

    @JsonView(CommonView.PublicView.class)
    private String phone;

    @JsonView(CommonView.DetailView.class)
    private String email;

    @JsonView(CommonView.DetailView.class)
    private PriceDataSource priceDataSource;

    @NotNull
    @JsonView(CommonView.PublicView.class)
    private Currency currency;

    @NotNull
    @JsonView(CommonView.DetailView.class)
    private VendorType type;

    @JsonView(CommonView.PublicView.class)
    private Double discount;

    @JsonView(CommonView.PublicView.class)
    private Double usDiscount;

    @JsonView(CommonView.DetailView.class)
    private Double markup;

    @JsonView(CommonView.PublicView.class)
    private Boolean isMarkupOverwriteGlobalSetting = false; // may have unexpected vendor update

    @JsonView(CommonView.PublicView.class)
    private Long prepaid;

    @JsonView(CommonView.DetailView.class)
    private Double freight;

    @JsonView(CommonView.DetailView.class)
    private Double brokerage;

    @JsonView(CommonView.DetailView.class)
    private Double duty;

    @JsonView(CommonView.PublicView.class)
    private Boolean isDutyOverwriteGlobalSetting = false; // may have unexpected vendor update

   ......

    @JsonView(CommonView.HideView.class)
    private Long addressId;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof TblVendorDTO)) {
            return false;
        }

        TblVendorDTO tblVendorDTO = (TblVendorDTO) o;
        if (this.id == null) {
            return false;
        }
        return Objects.equals(this.id, tblVendorDTO.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.id);
    }

    // prettier-ignore
    @Override
    public String toString() {
        return "TblVendorDTO{" +
            "id=" + getId() +
            ", name='" + getName() + "'" +
            ", externalId=" + getExternalId() +
            ", phone='" + getPhone() + "'" +
            ", email='" + getEmail() + "'" +
            ", priceDataSource='" + getPriceDataSource() + "'" +
            ", currency='" + getCurrency() + "'" +
            ", type='" + getType() + "'" +
            ", discount=" + getDiscount() +
            ", usDiscount=" + getUsDiscount() +
            ", markup=" + getMarkup() +
            ", isMarkupOverwriteGlobalSetting='" + getIsMarkupOverwriteGlobalSetting() + "'" +
            ", prepaid=" + getPrepaid() +
            ", freight=" + getFreight() +
            ", brokerage=" + getBrokerage() +
            ", duty=" + getDuty() +
            ", isDutyOverwriteGlobalSetting='" + getIsDutyOverwriteGlobalSetting() + "'" +
            ", isActive='" + getIsActive() + "'" +
            ", restockCharge=" + getRestockCharge() +
            ", leadTime=" + getLeadTime() +
            ", leadTimeType='" + getLeadTimeType() + "'" +
            ", returnPolicyShortDescription='" + getReturnPolicyShortDescription() + "'" +
            ", remark='" + getRemark() + "'" +
            ", address=" + getAddress() +
            "}";
    }
}

The Auditing entity, NO lombok annotation is used here

public abstract class AbstractAuditingDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonView(CommonView.PublicView.class)
    @ReadOnlyProperty
    private String createdBy;

    @JsonView(CommonView.PublicView.class)
    @ReadOnlyProperty
    private Instant createdDate = Instant.now();

    @JsonView(CommonView.PublicView.class)
    private String lastModifiedBy;

    @JsonView(CommonView.PublicView.class)
    private Instant lastModifiedDate = Instant.now();

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Instant getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Instant createdDate) {
        this.createdDate = createdDate;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public Instant getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Instant lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

We also use annotation like @Slf4j in our service classes:

@Service
@Transactional
@Slf4j
public class TblAreaService {

    private static final String entityName = "Area";

    private final TblAreaRepository tblAreaRepository;

    private final TblAreaMapper tblAreaMapper;

    public TblAreaService(TblAreaRepository tblAreaRepository, TblAreaMapper tblAreaMapper) {
        this.tblAreaRepository = tblAreaRepository;
        this.tblAreaMapper = tblAreaMapper;
    }

    /**
     * Save a tblArea.
     *
     * @param tblAreaDTO the entity to save.
     * @return the persisted entity.
     */
    public TblAreaDTO save(TblAreaDTO tblAreaDTO) {
        log.debug("Request to save TblArea : {}", tblAreaDTO);
        TblArea tblArea = tblAreaMapper.toEntity(tblAreaDTO);
        tblArea = tblAreaRepository.save(tblArea);
        return tblAreaMapper.toDto(tblArea);
    }
    ......

Lastly we use lombok annotation like @NoArgsConstructor in some entity classes. Note here we does not use @ Data

import com.emonster.saleserp.domain.enumeration.Currency;
import com.emonster.saleserp.domain.enumeration.OrderReturnType;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import javax.validation.constraints.*;

import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.OptimisticLocking;

/**
 * A TblOrderReturnPart.
 */
@Entity
@Table(name = "tbl_order_return_part")
@NoArgsConstructor
@OptimisticLocking(type = OptimisticLockType.DIRTY)
@DynamicUpdate
public class TblOrderReturnPart extends AbstractAuditingEntity {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(name = "type", nullable = false)
    private OrderReturnType type = OrderReturnType.RETURNTOVENDOR;

    @NotNull
    @Column(name = "quantity", nullable = false)
    private Long quantity;

    @NotNull
    @Column(name = "returned_to_vendor_quantity", nullable = false)
    private Long returnedToVendorQuantity = 0L;

    @NotNull
    @Column(name = "returned_to_stock_quantity", nullable = false)
    private Long returnedToStockQuantity = 0L;

    @NotNull
    @Column(name = "received_quantity", nullable = false)
    private Long receivedQuantity = 0L;

    @Column(name = "refund_net_amount")
    private Long refundNetAmount = 0L;

    @Column(name = "refund_tax_amount")
    private Long refundTaxAmount = 0L;

    @Column(name = "refund_eco_fee_amount")
    private Long refundEcoFeeAmount = 0L;

    @Column(name = "duty")
    private Long duty = 0L;

    @Column(name = "brokerage")
    private Long brokerage = 0L;

    @Column(name = "tariff")
    private Long tariff = 0L;

    @Column(name = "vendor_restocking_fee")
    private Long vendorRestockingFee = 0L;

    @Column(name = "restocking_fee")
    private Long restockingFee = 0L;

    @Column(name = "original_cost")
    private Long originalCost;

    @Column(name = "original_landed_cost")
    private Long originalLandedCost;

    @Column(name = "original_markup")
    private Double originalMarkup;

    @Column(name = "original_unit_price")
    private Long originalUnitPrice;

    @Column(name = "original_eco_fee_amount")
    private Long originalEcoFeeAmount;

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(name = "original_currency", nullable = false)
    private Currency originalCurrency;

    @Lob
    @Column(name = "return_reason", nullable = false)
    private String returnReason;

    @Lob
    @Column(name = "additional_reason")
    private String additionalReason;

    @Lob
    @Column(name = "remark")
    private String remark;

    @OneToMany(mappedBy = "orderReturnPart")
    @JsonIgnoreProperties(
        value = { "part", "purchaseOrderPart", "releasePurchaseOrderPart", "customerInvoice", "orderReturnPart" },
        allowSetters = true
    )
    private List<TblCusInvReleasePart> customerInvoiceReleaseParts = new ArrayList<>();

    @OneToMany(mappedBy = "orderReturnPart")
    @Fetch(FetchMode.SUBSELECT)
    @JsonIgnoreProperties(
        value = { "inventory", "fromInventoryShelf", "toInventoryShelf", "part", "releasePurchaseOrderPart", "request", "orderReturnPart" },
        allowSetters = true
    )
    private List<TblWarehouseRequestEntry> warehouseRequestEntries = new ArrayList<>();

    @OneToMany(mappedBy = "orderReturnPart", cascade = CascadeType.ALL)
    @Fetch(FetchMode.SUBSELECT)
    @JsonIgnoreProperties(
        value = { "warehouse", "part", "purchaseOrderPart", "release", "inventory", "orderReturnPart" },
        allowSetters = true
    )
    private List<TblInventoryAllocation> inventoryAllocations = new ArrayList<>();

    @OneToMany(mappedBy = "orderReturnPart", cascade = CascadeType.ALL)
    @Fetch(FetchMode.SUBSELECT)
    @JsonIgnoreProperties(value = { "inventory", "shelf", "orderReturnPart" }, allowSetters = true)
    private List<TblInventoryShelf> inventoryShelves = new ArrayList<>();

    @ManyToOne
    @JsonIgnoreProperties(
        value = {
            "retailPaymentParts",
            "cusInvReleaseParts",
            "purchaseOrderParts",
            "releasePurchaseOrderParts",
            "changeOrderParts",
            "inventoryAllocations",
            "requestEntries",
            "orderReturnParts",
            "customSpecFiles",
            "product",
            "area",
            "priceLevel",
            "warrantyPeriod",
            "quote",
            "order",
        },
        allowSetters = true
    )
    private TblPart part;
    .......
PterX commented 1 year ago

same problem, but i need lombok

iamfreeman commented 1 year ago

@testforstephen , I tried to install different old verison of "Language Support for Java(TM) by Red Hat", it turns out the lombok issue first came out at v1.11.0, and got worse at v1.12.0

jdneo commented 1 year ago

I can take a look if changing the scheduling mechanism (for publishing diagnostic jobs) can help the completion perf.

testforstephen commented 1 year ago

@testforstephen , I tried to install different old verison of "Language Support for Java(TM) by Red Hat", it turns out the lombok issue first came out at v1.11.0, and got worse at v1.12.0

@iamfreeman thanks for the test. In v1.11.0, it introduces a new feature about annotation based null analysis, that might have impact on compiling, you can try to disable it via setting "java.compile.nullAnalysis.mode": "disabled".

FabianLinn commented 1 year ago

Came to this issue because i have similar problems. Got nullAnalysis mode disabled, seems not to solve it. My project is a smaller one, but Lombok usage is quite likewise then mentionned.

jdneo commented 1 year ago

Roughly did a profiling on a Java class containing 200 member fields with the Lombok @Data annotation.

image

It looks like the publish diagnostic jobs takes a lot of CPU time. That might because the publish diagnostic jobs will invoke .reconcile() to build the AST, where the Lombok will take part into this process to insert those methods.

One thing we could try now is to make the publish diagnostic job scheduling be smarter. Instead of scheduling it after 400ms, we could make the time adaptive: like what we did before in this PR.

On the other hand, it still worths to investigating which changes at the Lombok side/upstream JDT downgrade the perf.

I'll first work on the first approach.

jdneo commented 1 year ago

@FabianLinn @iamfreeman @PterX

Here is a private build which changes the diagnostic publishing scheduling: download

Could you try to install it and let me know if the problem can be mitigated? (try typing and completion for multiple times since the adaptive debounce needs several rounds of invocation to 'correct' the time)

Note: The private build does not self-contain the required JRE for the extension. Please make sure you have JDK 17 installed locally.

jdneo commented 1 year ago

I've raised a PR to change the scheduling of the diagnostic job: https://github.com/eclipse/eclipse.jdt.ls/pull/2443. From my own experience, though the response time can become a little bit quicker, but the change is not significant, it's still laggy for a complex file.

@testforstephen , I tried to install different old verison of "Language Support for Java(TM) by Red Hat", it turns out the lombok issue first came out at v1.11.0, and got worse at v1.12.0

based on this information, I checked some changes we introduced in 1.11.0 and 1.12.0, and then find some potential candidates.

1.11.0

In 1.11.0, we introduced https://github.com/eclipse/eclipse.jdt.ls/pull/2232 to make the completion more context aware. But the tradeoff is that there will be much more tasks to do to make it context-aware. image

1.12.0

In 1.12.0, we introduced https://github.com/eclipse/eclipse.jdt.ls/pull/2339 to improve the code navigation for the lombok class, the changes to the JDT.toLocation() might enlarge the execution time. image

I'll do some more investigation and check if they are the assumption is right and if there is any way to fix them.

PterX commented 1 year ago

when i downgrade to 1.11.0 version, and upgrade to 1.14.0 version,It look like normal,I don't know why

iamfreeman commented 1 year ago

@jdneo , I have tried to install your version of Redhat, it does improve the performance a lot. Currently, it only wait for 1-2s to get the intellisense

snjeza commented 1 year ago

@iamfreeman Could you try https://github.com/snjeza/vscode-test/raw/master/java-1.15.3.vsix It includes

jdneo commented 1 year ago

@iamfreeman Thank you for the feedback! Meanwhile, there are some other works going on to improve the completion performance from different aspects. Hope we can limit the completion time < 1s in your case.

jdneo commented 1 year ago

@fbricon @rgrunber @testforstephen

BTW, I tried the impact of parameter guessing introduced in 1.11.0. Use the same experiment setup in https://github.com/eclipse/eclipse.jdt.ls/pull/2443. And trigger completion like this:

image

The profiling result shows that the impact is very limited. image

FabianLinn commented 1 year ago

@iamfreeman Could you try https://github.com/snjeza/vscode-test/raw/master/java-1.15.3.vsix It includes

* [ Skip generated methods when calculating the document symbols eclipse/eclipse.jdt.ls#2452](https://github.com/eclipse/eclipse.jdt.ls/pull/2452)

* [Make the debounce time of publish diagnostic job adaptive eclipse/eclipse.jdt.ls#2443](https://github.com/eclipse/eclipse.jdt.ls/pull/2443)

Installed it, but lombok support is fully disappeared. The JAVA based intellisense is really quick, but lombok Support is gone. Lombok based annotation (like @Slf4j) is also unusuable like DTO Annotated classes (e.g. @Data, @Getter, @Setter). Message is "the methot get[…] is undefined for [Class]", so it seems not to resolve Lombok annotations.

francescodedomenico commented 1 year ago

@snjeza I did try also the test build, built-in lombok support is gone which results in a broken Java build