diff --git a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/BackDependencyIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/BackDependencyIndexImpl.java index 542b83fbae08..2a02a627cca9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/BackDependencyIndexImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/BackDependencyIndexImpl.java @@ -3,7 +3,6 @@ package org.jetbrains.jps.dependency.impl; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.dependency.*; -import org.jetbrains.jps.dependency.diff.Difference; import org.jetbrains.jps.dependency.java.JvmNodeReferenceID; import org.jetbrains.jps.javac.Iterators; @@ -80,17 +79,9 @@ public abstract class BackDependencyIndexImpl implements BackDependencyIndex { toRemove.remove(refId); } } + myMap.removeValues(id, toRemove); } - if (!Iterators.isEmpty(toRemove)) { - Set dataAfter = Iterators.collect(getDependencies(id), new HashSet<>()); - dataAfter.removeAll(toRemove); - Iterators.collect(toAdd, dataAfter); - - myMap.update(id, dataAfter, Difference::diff); - } - else { - myMap.appendValues(id, toAdd); - } + myMap.appendValues(id, toAdd); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/CachingMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/CachingMultiMaplet.java index 1f3f2ec5d760..8f2433d5cf17 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/CachingMultiMaplet.java +++ b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/CachingMultiMaplet.java @@ -3,15 +3,12 @@ package org.jetbrains.jps.dependency.impl; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; -import com.intellij.util.containers.SmartHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.dependency.MultiMaplet; import org.jetbrains.jps.javac.Iterators; import java.io.IOException; import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; public class CachingMultiMaplet implements MultiMaplet { @@ -78,15 +75,11 @@ public class CachingMultiMaplet implements MultiMaplet { @Override public void removeValues(K key, @NotNull Iterable values) { if (!Iterators.isEmpty(values)) { - Set collection = Iterators.collect(myCache.get(key), new LinkedHashSet<>()); - if (collection.removeAll(values instanceof Set? ((Set)values) : Iterators.collect(values, new SmartHashSet<>()))) { - if (collection.isEmpty()) { - remove(key); - } - else { - myDelegate.put(key, collection); - myCache.put(key, collection); - } + try { + myDelegate.removeValues(key, values); + } + finally { + myCache.invalidate(key); } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/DependencyGraphImpl.java b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/DependencyGraphImpl.java index 15710114697f..a0d1fbbb350b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/DependencyGraphImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/DependencyGraphImpl.java @@ -243,14 +243,14 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr mySourceToNodesMap.remove(deletedSource); } - var updatedNodes = collect(flat(map(delta.getSources(), s -> getNodes(s))), Containers.createCustomPolicySet(DiffCapable::isSame, DiffCapable::diffHashCode)); + var updatedNodes = collect(flat(map(delta.getSources(), this::getNodes)), Containers.createCustomPolicySet(DiffCapable::isSame, DiffCapable::diffHashCode)); for (BackDependencyIndex index : getIndices()) { BackDependencyIndex deltaIndex = delta.getIndex(index.getName()); assert deltaIndex != null; index.integrate(diffResult.getDeletedNodes(), updatedNodes, deltaIndex); } - var deltaNodes = unique(map(flat(map(delta.getSources(), s -> delta.getNodes(s))), node -> node.getReferenceID())); + var deltaNodes = unique(map(flat(map(delta.getSources(), delta::getNodes)), node -> node.getReferenceID())); for (ReferenceID nodeID : deltaNodes) { Set sourcesAfter = collect(myNodeToSourcesMap.get(nodeID), new HashSet<>()); sourcesAfter.removeAll(delta.getBaseSources()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/PersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/PersistentMultiMaplet.java index 0f62d360d4f5..7851cc4e3b58 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/PersistentMultiMaplet.java +++ b/jps/jps-builders/src/org/jetbrains/jps/dependency/impl/PersistentMultiMaplet.java @@ -1,7 +1,6 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.jps.dependency.impl; -import com.intellij.util.containers.SmartHashSet; import com.intellij.util.io.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.storage.BuildDataCorruptedException; @@ -17,11 +16,12 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Supplier; public final class PersistentMultiMaplet> implements MultiMaplet { private final PersistentHashMap myMap; - private final DataExternalizer myValuesExternalizer; + private final DataExternalizer myValueExternalizer; private final C myEmptyCollection; private final Supplier myCollectionFactory; @@ -32,13 +32,14 @@ public final class PersistentMultiMaplet> implemen //noinspection unchecked myEmptyCollection = col instanceof List? (C)Collections.emptyList() : col instanceof Set? (C)Collections.emptySet() : col; - myValuesExternalizer = valueExternalizer; - + myValueExternalizer = valueExternalizer; + myMap = PersistentMapBuilder.newBuilder(mapFile, keyDescriptor, new DataExternalizer() { @Override - public void save(@NotNull DataOutput out, C value) throws IOException { - for (V v : value) { - valueExternalizer.save(out, v); + public void save(@NotNull DataOutput out, C data) throws IOException { + out.writeInt(data.size()); + for (V value : data) { + valueExternalizer.save(out, value); } } @@ -47,7 +48,12 @@ public final class PersistentMultiMaplet> implemen C acc = myCollectionFactory.get(); final DataInputStream stream = (DataInputStream)in; while (stream.available() > 0) { - acc.add(valueExternalizer.read(stream)); + int size = stream.readInt(); + Consumer appender = size > 0? acc::add : myEmptyCollection instanceof Set? acc::add : acc::remove; + size = Math.abs(size); + while (size-- > 0) { + appender.accept(valueExternalizer.read(stream)); + } } return acc; } @@ -128,8 +134,9 @@ public final class PersistentMultiMaplet> implemen myMap.appendData(key, new AppendablePersistentMap.ValueDataAppender() { @Override public void append(@NotNull DataOutput out) throws IOException { + out.writeInt(sizeOf(values)); for (V v : values) { - myValuesExternalizer.save(out, v); + myValueExternalizer.save(out, v); } } }); @@ -149,15 +156,15 @@ public final class PersistentMultiMaplet> implemen public void removeValues(K key, @NotNull Iterable values) { if (!Iterators.isEmpty(values)) { try { - C collection = get(key); - if (collection != myEmptyCollection && collection.removeAll(values instanceof Set? ((Set)values) : Iterators.collect(values, new SmartHashSet<>()))) { - if (collection.isEmpty()) { - myMap.remove(key); + myMap.appendData(key, new AppendablePersistentMap.ValueDataAppender() { + @Override + public void append(@NotNull DataOutput out) throws IOException { + out.writeInt(-sizeOf(values)); + for (V v : values) { + myValueExternalizer.save(out, v); + } } - else { - myMap.put(key, collection); - } - } + }); } catch (IOException e) { throw new BuildDataCorruptedException(e); @@ -189,4 +196,15 @@ public final class PersistentMultiMaplet> implemen public void flush() throws IOException { myMap.force(); } + + private static int sizeOf(Iterable seq) { + if (seq instanceof Collection) { + return ((Collection)seq).size(); + } + int size = 0; + for (Object v : seq) { + size++; + } + return size; + } }