mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
local history performance: use calculated context (workspace file, fileindex) for batch processing of virtual file events
This commit is contained in:
committed by
Maxim.Mossienko
parent
babc91c239
commit
a35b3d83a3
@@ -25,8 +25,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
public abstract class LocalHistory {
|
||||
public static final Object VFS_EVENT_REQUESTOR = new Object();
|
||||
|
||||
private static class LocalHistoryHolder {
|
||||
static final LocalHistory ourInstance = ApplicationManager.getApplication().getComponent(LocalHistory.class);
|
||||
}
|
||||
|
||||
public static LocalHistory getInstance() {
|
||||
return ApplicationManager.getApplication().getComponent(LocalHistory.class);
|
||||
return LocalHistoryHolder.ourInstance;
|
||||
}
|
||||
|
||||
public abstract LocalHistoryAction startAction(@Nullable String name);
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingRegistry;
|
||||
import com.intellij.openapi.vfs.newvfs.ManagingFS;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -66,21 +67,79 @@ public class IdeaGateway {
|
||||
|
||||
if (!f.isDirectory() && StringUtil.endsWith(f.getNameSequence(), ".class")) return false;
|
||||
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
LocalHistoryImpl.getInstanceImpl().dispatchPendingEvents();
|
||||
|
||||
VersionedFilterData versionedFilterData;
|
||||
VfsEventDispatchContext vfsEventDispatchContext = ourCurrentEventDispatchContext.get();
|
||||
if (vfsEventDispatchContext != null) {
|
||||
versionedFilterData = vfsEventDispatchContext.myFilterData;
|
||||
if (versionedFilterData == null) versionedFilterData = vfsEventDispatchContext.myFilterData = new VersionedFilterData();
|
||||
} else {
|
||||
versionedFilterData = new VersionedFilterData();
|
||||
}
|
||||
|
||||
boolean isInContent = false;
|
||||
for (Project each : openProjects) {
|
||||
if (each.isDefault()) continue;
|
||||
if (!each.isInitialized()) continue;
|
||||
if (Comparing.equal(each.getWorkspaceFile(), f)) return false;
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(each).getFileIndex();
|
||||
|
||||
int numberOfOpenProjects = versionedFilterData.myOpenedProjects.size();
|
||||
for (int i = 0; i < numberOfOpenProjects; ++i) {
|
||||
if (Comparing.equal(versionedFilterData.myWorkspaceFiles.get(i), f)) return false;
|
||||
ProjectFileIndex index = versionedFilterData.myProjectFileIndices.get(i);
|
||||
|
||||
if (index.isExcluded(f)) return false;
|
||||
isInContent |= index.isInContent(f);
|
||||
}
|
||||
if (shouldBeInContent && !isInContent) return false;
|
||||
|
||||
|
||||
// optimisation: FileTypeManager.isFileIgnored(f) already checked inside ProjectFileIndex.isIgnored()
|
||||
return openProjects.length != 0 || !FileTypeManager.getInstance().isFileIgnored(f);
|
||||
return numberOfOpenProjects != 0 || !FileTypeManager.getInstance().isFileIgnored(f);
|
||||
}
|
||||
|
||||
private static final ThreadLocal<VfsEventDispatchContext> ourCurrentEventDispatchContext = new ThreadLocal<>();
|
||||
|
||||
private static class VfsEventDispatchContext {
|
||||
final List<? extends VFileEvent> myEvents;
|
||||
final boolean myBeforeEvents;
|
||||
final VfsEventDispatchContext myPreviousContext;
|
||||
|
||||
VersionedFilterData myFilterData;
|
||||
|
||||
VfsEventDispatchContext(List<? extends VFileEvent> events, boolean beforeEvents, VfsEventDispatchContext context) {
|
||||
myEvents = events;
|
||||
myBeforeEvents = beforeEvents;
|
||||
myPreviousContext = context;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
ourCurrentEventDispatchContext.set(myPreviousContext);
|
||||
}
|
||||
}
|
||||
|
||||
public void runWithVfsEventsDispatchContext(List<? extends VFileEvent> events, boolean beforeEvents, Runnable action) {
|
||||
VfsEventDispatchContext vfsEventDispatchContext = new VfsEventDispatchContext(events, beforeEvents, ourCurrentEventDispatchContext.get());
|
||||
ourCurrentEventDispatchContext.set(vfsEventDispatchContext);
|
||||
try {
|
||||
action.run();
|
||||
} finally {
|
||||
vfsEventDispatchContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class VersionedFilterData {
|
||||
final List<Project> myOpenedProjects = new ArrayList<>();
|
||||
final List<ProjectFileIndex> myProjectFileIndices = new ArrayList<>();
|
||||
final List<VirtualFile> myWorkspaceFiles = new ArrayList<>();
|
||||
|
||||
VersionedFilterData() {
|
||||
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
|
||||
|
||||
for (Project each : openProjects) {
|
||||
if (each.isDefault()) continue;
|
||||
if (!each.isInitialized()) continue;
|
||||
|
||||
myWorkspaceFiles.add(each.getWorkspaceFile());
|
||||
myOpenedProjects.add(each);
|
||||
myProjectFileIndices.add(ProjectRootManager.getInstance(each).getFileIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areContentChangesVersioned(@NotNull VirtualFile f) {
|
||||
|
||||
+25
-1
@@ -23,10 +23,16 @@ import com.intellij.openapi.command.CommandListener;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements VirtualFileManagerListener, CommandListener {
|
||||
import java.util.List;
|
||||
|
||||
public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements VirtualFileManagerListener, CommandListener,
|
||||
BulkFileListener {
|
||||
private static final Key<Boolean> WAS_VERSIONED_KEY =
|
||||
Key.create(LocalHistoryEventDispatcher.class.getSimpleName() + ".WAS_VERSIONED_KEY");
|
||||
|
||||
@@ -193,4 +199,22 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V
|
||||
private boolean areContentChangesVersioned(VirtualFileEvent e) {
|
||||
return myGateway.areContentChangesVersioned(e.getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
myGateway.runWithVfsEventsDispatchContext(events, true, () -> {
|
||||
for (VFileEvent event : events) {
|
||||
BulkVirtualFileListenerAdapter.fireBefore(this, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
myGateway.runWithVfsEventsDispatchContext(events, false, () -> {
|
||||
for (VFileEvent event : events) {
|
||||
BulkVirtualFileListenerAdapter.fireAfter(this, event);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,8 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -47,6 +49,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static com.intellij.history.integration.LocalHistoryUtil.findRevisionIndexToRevert;
|
||||
|
||||
public class LocalHistoryImpl extends LocalHistory implements ApplicationComponent {
|
||||
private final MessageBus myBus;
|
||||
private MessageBusConnection myConnection;
|
||||
private ChangeList myChangeList;
|
||||
private LocalHistoryFacade myVcs;
|
||||
private IdeaGateway myGateway;
|
||||
@@ -60,6 +64,10 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
return (LocalHistoryImpl)getInstance();
|
||||
}
|
||||
|
||||
public LocalHistoryImpl(@NotNull MessageBus bus) {
|
||||
myBus = bus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && ApplicationManager.getApplication().isHeadlessEnvironment()) return;
|
||||
@@ -89,8 +97,10 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
|
||||
CommandProcessor.getInstance().addCommandListener(myEventDispatcher);
|
||||
|
||||
myConnection = myBus.connect();
|
||||
myConnection.subscribe(VirtualFileManager.VFS_CHANGES, myEventDispatcher);
|
||||
|
||||
VirtualFileManager fm = VirtualFileManager.getInstance();
|
||||
fm.addVirtualFileListener(myEventDispatcher);
|
||||
fm.addVirtualFileManagerListener(myEventDispatcher);
|
||||
|
||||
if (ApplicationManager.getApplication().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
@@ -126,8 +136,9 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
|
||||
long period = Registry.intValue("localHistory.daysToKeep") * 1000L * 60L * 60L * 24L;
|
||||
|
||||
myConnection.disconnect();
|
||||
myConnection = null;
|
||||
VirtualFileManager fm = VirtualFileManager.getInstance();
|
||||
fm.removeVirtualFileListener(myEventDispatcher);
|
||||
fm.removeVirtualFileManagerListener(myEventDispatcher);
|
||||
CommandProcessor.getInstance().removeCommandListener(myEventDispatcher);
|
||||
|
||||
@@ -143,6 +154,10 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
ShutDownTracker.getInstance().unregisterShutdownTask(myShutdownTask);
|
||||
}
|
||||
|
||||
protected void dispatchPendingEvents() {
|
||||
myConnection.deliverImmediately();
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void cleanupForNextTest() {
|
||||
disposeComponent();
|
||||
|
||||
Reference in New Issue
Block a user