Skip to content

Commit 807ee7e

Browse files
committed
Improve workspace open speeds by caching 'getAllResources' result and using identity indexOf in resource path comparison
1 parent 5288451 commit 807ee7e

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

recaf-core/src/main/java/software/coley/recaf/path/ResourcePathNode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import software.coley.collections.Maps;
66
import software.coley.collections.Unchecked;
77
import software.coley.recaf.info.Named;
8+
import software.coley.recaf.util.CollectionUtils;
89
import software.coley.recaf.workspace.model.Workspace;
910
import software.coley.recaf.workspace.model.bundle.Bundle;
1011
import software.coley.recaf.workspace.model.resource.WorkspaceFileResource;
@@ -142,7 +143,7 @@ public int localCompare(PathNode<?> o) {
142143

143144
// Show in order as in the workspace.
144145
List<WorkspaceResource> resources = workspace.getAllResources(false);
145-
return Integer.compare(resources.indexOf(resource), resources.indexOf(otherResource));
146+
return Integer.compare(CollectionUtils.identityIndexOf(resources, resource), CollectionUtils.identityIndexOf(resources, otherResource));
146147
} else {
147148
// Enforce some ordering. Not ideal but works.
148149
return Named.STRING_COMPARATOR.compare(
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package software.coley.recaf.util;
2+
3+
import jakarta.annotation.Nonnull;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Collection utilities that don't fit anywhere else.
9+
* These should ideally get migrated to <a href="https://github.com/Col-E/ExtraCollections">Extra-Collections</a>.
10+
*
11+
* @author Matt Coley
12+
*/
13+
public class CollectionUtils {
14+
/**
15+
* @param list
16+
* List to search through.
17+
* @param element
18+
* Element to search for.
19+
* @param <T>
20+
* Inferred element type.
21+
*
22+
* @return The index of the first occurrence of {@code element} in {@code list}, or -1 if not found.
23+
*/
24+
public static <T> int identityIndexOf(@Nonnull List<? extends T> list, T element) {
25+
for (int i = list.size(); i != 0; )
26+
if (element == list.get(--i))
27+
return i;
28+
return -1;
29+
}
30+
}

recaf-core/src/main/java/software/coley/recaf/workspace/model/BasicWorkspace.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public class BasicWorkspace implements Workspace {
2828
private final WorkspaceResource primary;
2929
private final List<WorkspaceResource> supporting = new ArrayList<>();
3030
private final List<WorkspaceResource> internal;
31+
private List<WorkspaceResource> cachedAllResourcesNoInternal;
32+
private List<WorkspaceResource> cachedAllResources;
3133

3234
/**
3335
* @param primary
@@ -92,6 +94,7 @@ public List<WorkspaceResource> getInternalSupportingResources() {
9294

9395
@Override
9496
public void addSupportingResource(@Nonnull WorkspaceResource resource) {
97+
cachedAllResources = null;
9598
supporting.add(resource);
9699
Unchecked.checkedForEach(modificationListeners, listener -> listener.onAddLibrary(this, resource),
97100
(listener, t) -> logger.error("Exception thrown when adding supporting resource", t));
@@ -101,6 +104,7 @@ public void addSupportingResource(@Nonnull WorkspaceResource resource) {
101104
public boolean removeSupportingResource(@Nonnull WorkspaceResource resource) {
102105
boolean remove = supporting.remove(resource);
103106
if (remove) {
107+
cachedAllResources = null;
104108
Unchecked.checkedForEach(modificationListeners, listener -> listener.onRemoveLibrary(this, resource),
105109
(listener, t) -> logger.error("Exception thrown when removing supporting resource", t));
106110
}
@@ -123,6 +127,24 @@ public void removeWorkspaceModificationListener(@Nonnull WorkspaceModificationLi
123127
modificationListeners.remove(listener);
124128
}
125129

130+
@Nonnull
131+
@Override
132+
public List<WorkspaceResource> getAllResources(boolean includeInternal) {
133+
// Cache the list of all resources since it is commonly used and the underlying stream
134+
// collection in the base implementation is expensive to compute.
135+
if (includeInternal) {
136+
List<WorkspaceResource> cached = this.cachedAllResources;
137+
if (cached != null)
138+
return cached;
139+
return this.cachedAllResources = Workspace.super.getAllResources(false);
140+
} else {
141+
List<WorkspaceResource> cached = this.cachedAllResourcesNoInternal;
142+
if (cached != null)
143+
return cached;
144+
return this.cachedAllResourcesNoInternal = Workspace.super.getAllResources(false);
145+
}
146+
}
147+
126148
/**
127149
* Called by {@link WorkspaceManager} when the workspace is closed.
128150
*/

0 commit comments

Comments
 (0)