From 8576d001513602f14f2befa4bcbe613a67d3ef94 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 20 Nov 2009 14:58:16 +0300 Subject: [PATCH] reduce number of DelegateDisposables faster dispose --- .../codeInsight/daemon/impl/FileStatusMap.java | 1 + .../openapi/vfs/impl/VirtualFilePointerImpl.java | 2 +- .../vfs/impl/VirtualFilePointerManagerImpl.java | 57 ++++++++++++++++++++-- .../src/com/intellij/openapi/util/Disposer.java | 17 +++++++ 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/FileStatusMap.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/FileStatusMap.java index d1923fd5a4..b524011472 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/FileStatusMap.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/FileStatusMap.java @@ -146,6 +146,7 @@ public class FileStatusMap implements Disposable { return true; } }); + s.append(")"); return s.toString(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java index c9355e7fef..e5dfdf9f60 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java @@ -37,7 +37,7 @@ public class VirtualFilePointerImpl extends UserDataHolderBase implements Virtua private final VirtualFileManager myVirtualFileManager; private final VirtualFilePointerListener myListener; private boolean disposed = false; - private int useCount; + int useCount; private long myLastUpdated = -1; private static final Key CREATE_TRACE = Key.create("CREATION_TRACE"); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index b17c4b4706..fbf33e8ab2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -18,10 +18,12 @@ package com.intellij.openapi.vfs.impl; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.objectTree.ObjectNode; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; @@ -38,6 +40,8 @@ import org.jetbrains.annotations.TestOnly; import java.util.*; public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager implements ApplicationComponent{ + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl"); + // guarded by this private final Map> myUrlToPointerMaps = new LinkedHashMap>(); @@ -211,12 +215,23 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } else { //already registered - Disposer.register(parentDisposable, new DelegatingDisposable(pointer)); + register(parentDisposable, pointer); } return pointer; } + private static void register(Disposable parentDisposable, VirtualFilePointerImpl pointer) { + DelegatingDisposable delegating = new DelegatingDisposable(pointer); + DelegatingDisposable registered = Disposer.findRegisteredObject(parentDisposable, delegating); + if (registered == null) { + Disposer.register(parentDisposable, delegating); + } + else { + registered.disposeCount++; + } + } + private static String cleanupPath(String path, String protocol) { path = FileUtil.toSystemIndependentName(path); @@ -495,12 +510,15 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp private static class DelegatingDisposable implements Disposable { private final VirtualFilePointerImpl myPointer; + private int disposeCount = 1; - private DelegatingDisposable(VirtualFilePointerImpl pointer) { + private DelegatingDisposable(@NotNull VirtualFilePointerImpl pointer) { myPointer = pointer; } public void dispose() { + myPointer.useCount -= disposeCount-1; + LOG.assertTrue(myPointer.useCount > 0); myPointer.dispose(); } @@ -508,6 +526,17 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp public String toString() { return "D:" + myPointer.toString(); } + + @Override + public boolean equals(Object o) { + DelegatingDisposable that = (DelegatingDisposable)o; + return myPointer == that.myPointer; + } + + @Override + public int hashCode() { + return myPointer.hashCode(); + } } @TestOnly @@ -520,7 +549,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } @TestOnly - public int coundDupContainers() { + public int countDupContainers() { Map c = new THashMap(); for (VirtualFilePointerContainerImpl container : myContainers) { Integer count = c.get(container); @@ -536,4 +565,26 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } return i; } + + @TestOnly + public static int countMaxRefCount() { + int result = 0; + for (Disposable disposable : Disposer.getTree().getRootObjects()) { + result = calcMaxRefCount(disposable, result); + } + return result; + } + + private static int calcMaxRefCount(Disposable disposable, int result) { + if (disposable instanceof DelegatingDisposable) { + result = Math.max(((DelegatingDisposable)disposable).disposeCount, result); + } + + for (ObjectNode node : Disposer.getTree().getNode(disposable).getChildren()) { + result = calcMaxRefCount(node.getObject(), result); + } + return result; + } + + } diff --git a/platform/util/src/com/intellij/openapi/util/Disposer.java b/platform/util/src/com/intellij/openapi/util/Disposer.java index d2b2d082f6..da84e90492 100644 --- a/platform/util/src/com/intellij/openapi/util/Disposer.java +++ b/platform/util/src/com/intellij/openapi/util/Disposer.java @@ -16,6 +16,7 @@ package com.intellij.openapi.util; import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.objectTree.ObjectNode; import com.intellij.openapi.util.objectTree.ObjectTree; import com.intellij.openapi.util.objectTree.ObjectTreeAction; import com.intellij.util.ReflectionUtil; @@ -127,4 +128,20 @@ public class Disposer { ReflectionUtil.resetField(object, each); } } + + /** + * @return object registered on parentDisposable which is equal to object, or null + */ + @Nullable + public static T findRegisteredObject(@NotNull Disposable parentDisposable, @NotNull T object) { + ObjectNode parentNode = getTree().getNode(parentDisposable); + if (parentNode == null) return null; + for (ObjectNode node : parentNode.getChildren()) { + Disposable nodeObject = node.getObject(); + if (nodeObject.equals(object)) { + return (T)nodeObject; + } + } + return null; + } } -- 2.11.4.GIT