"'YourPlugin' might be slowing things down" reported when invoking the IDE's SynchronizeAction from the EDT

I had a user report a “…might be slowing things down” freeze stack traces with the following:

Freeze in EDT for 15 seconds
Sampled time: 7400ms, sampling rate: 100ms, GC time: 332ms (3%), Class loading: 0%

com.intellij.diagnostic.Freeze
    at java.base@21.0.6/java.lang.Object.wait0(Native Method)
    at java.base@21.0.6/java.lang.Object.wait(Object.java:366)
    at java.base@21.0.6/java.lang.Object.wait(Object.java:339)
    at com.intellij.openapi.application.impl.RunSuspend.await(RunSuspend.kt:36)
    at com.intellij.openapi.application.impl.RunSuspendKt.runSuspend(RunSuspend.kt:14)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.getWritePermit(AnyThreadWriteThreadingSupport.kt:688)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.startWrite$lambda$7(AnyThreadWriteThreadingSupport.kt:416)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport$$Lambda/0x000000d001bf5010.invoke(Unknown Source)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.measureWriteLock(AnyThreadWriteThreadingSupport.kt:562)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.startWrite(AnyThreadWriteThreadingSupport.kt:416)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:387)
    at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:383)
    at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:907)
    at com.intellij.openapi.application.WriteAction.run(WriteAction.java:84)
    at com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl.doSaveDocument(FileDocumentManagerImpl.java:386)
    at com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl.saveDocuments(FileDocumentManagerImpl.java:303)
    at com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl.saveAllDocuments(FileDocumentManagerImpl.java:278)
    at com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl.saveAllDocuments(FileDocumentManagerImpl.java:271)
    at com.intellij.ide.actions.SynchronizeAction.actionPerformed(SynchronizeAction.java:16)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.doPerformActionOrShowPopup(ActionUtil.kt:374)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAwareWithCallbacks$lambda$7(ActionUtil.kt:343)
    at com.intellij.openapi.actionSystem.ex.ActionUtil$$Lambda/0x000000d00371ed28.run(Unknown Source)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.performWithActionCallbacks(ActionManagerImpl.kt:1173)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAwareWithCallbacks(ActionUtil.kt:342)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImplKt.doPerformAction$lambda$1(ActionManagerImpl.kt:1334)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImplKt$$Lambda/0x000000d00371e8a8.run(Unknown Source)
    at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:109)
    at com.intellij.openapi.application.TransactionGuardImpl.performUserActivity(TransactionGuardImpl.java:98)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImplKt.doPerformAction(ActionManagerImpl.kt:1318)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImplKt.tryToExecuteNow(ActionManagerImpl.kt:1371)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImplKt.access$tryToExecuteNow(ActionManagerImpl.kt:1)
    at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.tryToExecute(ActionManagerImpl.kt:1224)
    at com.illuminatedcloud.intellij.util.IcFileUtil.lambda$synchronizeFiles$8(SourceFile:723)

Now this is a situation where my plugin has generated an extensive set of project-specific TypeScript type definitions into the project directory structure that will be used as a TypeScript library, and it then needs to force the IDE to refresh the VFS so that it sees all of those library files.

In this specific situation, I found that just performing a refresh of VFS wasn’t working consistently, but if I then explicitly used File | Reload All from Disk, it caught up properly. As a result, I just added a method, IcFileUtil#synchronizeFiles(), that calls the following (simplified for sake of example) from the EDT just as if the user had explicitly triggered that action:

DumService.getInstance(project).smartInvokeLater(() ->
    ActionManager.getInstance().execute(ActionManager.getInstance().getAction(IdeActions.ACTION_SYNCHRONIZE), ...);
);

So this leads to two questions:

First, is there perhaps a better way to do what I’m needing to do here, i.e., refreshing VFS 100% reliably when I know that files have changed that need to be refreshed for the project to operate properly? I’m wondering if perhaps I should be calling VirtualFileManager#refreshFileWithoutFileWatcher(true) just as SynchronizeAction does.

UPDATE: It looks like calling SaveAndSyncHandler.getInstance().refreshOpenFiles() on the EDT followed by VirtualFileManager.getInstance().refreshWithoutFileWatcher(true) on a BGT may do the trick. That avoids SynchronizeAction’s FileDocumentManager.getInstance().saveAllDocuments() call that’s the main culprit in the stack trace above, and that’s not needed in this scenario anyway.

Second, how does the line gets drawn between third-party plugin behavior and core IDE behavior when attributing “…might be slowing things down” to one or the other? Yes, the stack trace for this thread technically goes through my plugin, but in this case, that EDT task logic is literally just using the IDE’s ActionManager to execute an IDE action.

Don’t get me wrong…I’m finding this information exceptionally useful and am actively using it to address as many of these types of behaviors as possible in my plugin, but for something like this, if I’m unable to find a reliable alternative for refreshing the VFS consistently, I’m concerned that such a confidence-shattering message might continue to be presented to users of my plugin for something not entirely under my control. Hopefully that concern makes sense…

Hi! Could you please share more/all thread-dumps for the report. The cause is a bit unclear to me from the one EDT trace since it was waiting for write action

Unfortunately that’s the only portion that the end user provided. I’ll ask if he can provide more details if/when it happens again…though hopefully it won’t with the changes I’ve made to avoid the need for the write lock since it’s no longer trying to commit all uncommitted documents just to refresh VFS.

Check the directory threadDumps-freeze at the timestamp of the slow log. Should give you a full thread dump and you can see which thread holds the lock.

At least that could be a way to investigate it.

Yeah, I’d asked the end user for the full thread dump at the same time stamp, but this happened late last week and the user hasn’t responded. My guess is that I’ll only get a full thread dump if/when this happens again.

1 Like

Will be nice if the default error reporter could attach a full thread dump, at least when we have this kind of error.

2 Likes

100% agreed since that’s what’s being requested to diagnose the total thread state anyway.

See also

@yuriy.artamonov I also got a similar report just at the end of last year (NixOS/nix-idea#95). In my case, I noticed that my parser is too slow in some cases. Anyway, I also noticed that older versions of IntelliJ don’t freeze. The freeze only occurs on versions from 2024.3 onwards. It looks like IntelliJ 2024.2.6 and earlier versions were effectively aborting the parsing when you made additional modifications. Based on the method name, I suspect ProgressIndicatorUtils.runActionAndCancelBeforeWrite is supposed to implement this behavior. However, this doesn’t seem to work anymore.

Could you share an example thread dumps where parser seems like not canceling? We can confirm this issue or reveal the real cause then

I would like to comment here that - Actions are not meant to be used as API. They are in fact are non-reusable UI elements. This rule is often ignored though. But please don’t ignore it here, as SynchronizeAction is a very bad way to sync files after IO operations outside of VFS. The only thing you need usually is starting VFS refresh on a background thread, via

VirtualFile vf = ...;

VfsUtil.markDirtyAndRefresh(
    true,   // async refresh
    true,   // recursive — refresh children too
    true,   // reload from disk
    vf
);

You may need to LocalFileSystem.getInstance().findFileByIoFile() for a directory by path first via VFS API.

P.S: DumbService.getInstance(project).smartInvokeLater is not needed to sync VFS, as it is a lower level mechanism than indexes and works without them

1 Like

Here is a thread dump of IntelliJ 2025.3.1:
threads_report.txt (395.4 KB)

The first thread is the parser, which started when I hit backspace to remove the ' character. The second thread is the AWT thread trying to re-add the ' after I re-typed it. However, the AWT thread is blocked waiting for the parser started earlier. At least that is my interpretation. (The stack trace actually looks different compared to my earlier debugging on older versions of IntelliJ.)

NixOS/nix-idea#95 also describes how to reproduce this specific scenario with the latest version of the plugin.

HI Johannes,

Could you create a ticket on https://youtrack.jetbrains.com/newIssue and attach a CPU snapshot of the freeze and the full log folder after the freeze just has happened. Thanks in advance.