Skip to content

Run long-spanning tasks cancellably on background in the (Java) LSP server.#7708

Draft
lahodaj wants to merge 1348 commits intoapache:masterfrom
lahodaj:java-lsp-server-compute-long-spanning-tasks-cancellably-on-background
Draft

Run long-spanning tasks cancellably on background in the (Java) LSP server.#7708
lahodaj wants to merge 1348 commits intoapache:masterfrom
lahodaj:java-lsp-server-compute-long-spanning-tasks-cancellably-on-background

Conversation

@lahodaj
Copy link
Copy Markdown
Contributor

@lahodaj lahodaj commented Aug 29, 2024

@jtulach reported the code completion inside VS Code is sometimes slow for him. I was thinking of that, and experimenting, and I think at least part of the problem is that tasks that should be background tasks are not properly cancellable in the VS Code (Java) server.

I was doing experiments on:
https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

and it seemed there were two (current) particular pain points:

  • diagnostics (especially hints) computation, which can take a fairly long time to compute
  • semantic coloring computation, which can also take some time to compute

Neither of these can be cancelled when the request to compute code completion. This draft is attempting to improve that, and run diagnostics and semantic coloring in a cancellable way.

It only properly cancels for Java sources at this time, for other sources runs only the CompletableFuture cancel will work. Some work on Schedulers will be needed to fully enable this for non-Java sources, but I suspect this can wait

I also have a separate PR that adds additional logging for code completion:
#7815

@lahodaj
Copy link
Copy Markdown
Contributor Author

lahodaj commented Oct 9, 2024

I think we need to make progress on this.

@lahodaj lahodaj marked this pull request as ready for review October 9, 2024 13:55
@lahodaj lahodaj added Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) LSP [ci] enable Language Server Protocol tests VSCode Extension labels Oct 9, 2024
@lahodaj lahodaj added this to the NB24 milestone Oct 9, 2024
@apache apache locked and limited conversation to collaborators Oct 9, 2024
@apache apache unlocked this conversation Oct 9, 2024
@lahodaj lahodaj changed the title Prototype: run long-spanning tasks cancellably on background in the (Java) LSP server. Run long-spanning tasks cancellably on background in the (Java) LSP server. Oct 9, 2024
@lahodaj lahodaj requested review from dbalek and sdedic October 9, 2024 14:15
@ebarboni ebarboni modified the milestones: NB24, NB25 Oct 22, 2024
@lahodaj lahodaj force-pushed the java-lsp-server-compute-long-spanning-tasks-cancellably-on-background branch from a768cee to 71e959b Compare November 29, 2024 14:12
@lahodaj
Copy link
Copy Markdown
Contributor Author

lahodaj commented Nov 29, 2024

FWIW: I've changed the implementation to an explicit priority "queue", as the original patch with injecting tasks in the editor background infrastructure proved to be too complex, at least for now.

@lahodaj lahodaj force-pushed the java-lsp-server-compute-long-spanning-tasks-cancellably-on-background branch from 49bb7f8 to a7f0d23 Compare December 3, 2024 10:08
@lahodaj
Copy link
Copy Markdown
Contributor Author

lahodaj commented Dec 3, 2024

I limitation of this way to cancel things is that it cannot stop computations inside javac/parser. Unlike the previous round which used the "editor" tasks, which can stop even javac/parser.

But, this patch:

  • should provide an improvement compared to the current state
  • should allow various features use the abstraction - and then we might be able to improve the abstraction, without (significantly) re-writing the features.

Copy link
Copy Markdown
Contributor

@eirikbakke eirikbakke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just passing by with some comments/questions... I'm not very familiar with this area in the codebase.

public void cancel();
}

public final class CancelCheck {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be a public class? It is currently used only within this class.

}

public void registerCancel(CancelCallback callback) {
cancelCallback.set(callback);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps throw an IllegalStateException if a callback is already registered.

void cancel() {
cancelled.set(true);

CancelCallback callback = cancelCallback.get();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be easier to verify the thread-safety of these methods if the accesses to cancelled and cancelCallback were synchronized as a unit, rather than just being individually protected by AtomicBoolean/AtomicReference.

But in practice I assume registerCancel is going to be called up-front, before concurrent accesses start.

private final P data;
private final CompletableFuture<R> result;

public TaskDescription(CancellableTask<P, R> task, P data, CompletableFuture<R> result) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add null checks on parameters so that NPEs happen immediately and with a useful stack trace, rather than with a delay.


private CancelCheck() {}

public boolean isCancelled() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be called somewhere from TextDocumentServiceImpl? Whenever I do cancelable operations, I usually have a loop of batch operations with an if (isCanceled()) break; somewhere.

@ebarboni ebarboni modified the milestones: NB25, NB26 Jan 24, 2025
@neilcsmith-net neilcsmith-net modified the milestones: NB26, NB27 Apr 16, 2025
@neilcsmith-net neilcsmith-net removed this from the NB27 milestone Jul 18, 2025
@neilcsmith-net neilcsmith-net added the stale No recent activity - likely to be closed. label Jul 18, 2025
@neilcsmith-net neilcsmith-net marked this pull request as draft July 18, 2025 14:24
mbien and others added 30 commits April 2, 2026 00:07
Move Splash initialization to EDT and make it no longer modal
[GITHUB-6925] Fixing debugger.jpda.truffle tests.
the tests can run on regular JDKs, GraalVM's polyglot features became
dependencies in pasts.

the modules are already covered by the java, debugger, ide, profiler
and platform jobs (only the nashorn module needed to be moved).
The warning said "No enabled eligible for injection beans are found",
because the filter class did not check "jakarta." namespace
CDI: fix injection warning for jakarta predefined bean classes
Export-Package entries are not just comma separated values, but can contain
parameters, which themselves can contain commas in quoted strings. These cases
need to be handled correctly.
Move the setting of awtAppClassName for XToolkit into Main so that
it is set before splash and import dialogs are created. This fixes
issues with duplicate dock icons caused by incorrect WM_CLASS
derived from this field value.
## Skip firing events for up-to-date 

Skip firing events for up-to-date files that are not
yet in the cache, since UPTODATE is the default for managed files. 
This drastically reduces the time spent in the refreshStatusesBatch method on big repositories executed when Commit dialog opens. For example, on the Netbeans repository, from around 8 seconds to 20ms.

## Batch status change notifications

Batch status change notifications to avoid per-file event overhead.

Replace per-file PROP_FILE_STATUS_CHANGED firing in refreshStatusesBatch
with a single PROP_FILES_STATUS_CHANGED batch event, eliminating 100k
redundant propertyChange/schedule/SwingUtilities.invokeLater calls on
first load. This improves performance a bit because it eliminates many method calls. 
However, in the end, the number of files changed is the same so the event handler 
still needs to process all of them.

## Move status updates to a background thread

File status update requires I/O operation to refresh files metadata from FS. This is very slow when many files need to be updated. Moving them to a background thread offloads this slow operation from the main thread.
Updates can run asynchronously without blocking the main thread that fires the status events, they just update UI hints, they have no impact no behavior.
For the whole Netbeans repository, this shortens the time it takes to complete the firePropertyChange event from 6 seconds to 1 second.
Move setting of awtAppClassName from MainWindow to Main
Use a regular expression to not consider comma between quote while co…
make jnlp build process runnable again
 - use Data*Streams instead of Object*Streams
 - simplify file format (no XML)
 - code renovation and other minor optimizations

results in 4x faster cache loading times (readCache() and
calculateParents() methods)

minor:
 - ModuleManager.EnableContext: List -> Set for field solely used for
   contains() in inner loop
 - Module: data loading can synchronize on instance instead of class
   (DATA_LOCK no longer static)

note:
The IO utility class calls Dependency#create using MethodHandle to
avoid having to make it public API or introduce a split package.
Improve startup cache loading performance
Improving code completion in presence of local classes.
FISH-12969 Payara Server Startup Fails in Apache NetBeans IDE Due to the CRaCCheckpointTo Option
…optimization-skip-no-update

Speed up loading file statuses in Git commit dialog by batching events and skipping events for up-to-date files
Speeds up GitClient.getStatus() by deferring expensive evaluation of object Ids, which often compute file content hash, to evaluate them lazily only when needed.

On Netbeans repository with a lot of files, this speeds up GitClient.getStatus() execution from 4 seconds to 1 second.
…optimization

StatusCommand: Optimize git status by deferring getObjectId() calls
Newer bouncy castle JARs declare an import of the java.io package. This
is rejected by the manifest verification in the equinox version NetBeans
uses wrapped into Netbinox.

This change deactivates the check in equinox that rejects that entry.

Additionally the instructions for building the patched equinox version
were updated.

Closes: apache#8894
…date

Enable loading of bundles importing java.-packages and update Bouncy Castle to fix jgit signing
adjusted RevWalk max flags constant since it diverges from javadoc and
added tripwire test in case it changes again in future.
Update jgit from 7.2.0 to 7.6.0
…anning-tasks-cancellably-on-background' into java-lsp-server-compute-long-spanning-tasks-cancellably-on-background
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) LSP [ci] enable Language Server Protocol tests stale No recent activity - likely to be closed. VSCode Extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.