JPS mappings for incremental compilation refactoring: flush caches and PHM on low memory; use output file path relative to compile chunk output

GitOrigin-RevId: 774ee124a3dc75085499bf35fd999b0fe5a572bb
This commit is contained in:
Eugene Zhuravlev
2023-11-15 11:42:34 +01:00
committed by intellij-monorepo-bot
parent f49bc2ca79
commit 1dfd7c7e40
11 changed files with 82 additions and 28 deletions

View File

@@ -0,0 +1,24 @@
// 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;
import org.jetbrains.annotations.NotNull;
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
public interface BaseMaplet<K> extends Closeable, Flushable {
boolean containsKey(K key);
void remove(K key);
@NotNull
Iterable<K> getKeys();
@Override
void close() throws IOException;
@Override
void flush() throws IOException;
}

View File

@@ -3,21 +3,10 @@ package org.jetbrains.jps.dependency;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
import java.io.IOException;
public interface Maplet<K, V> extends Closeable {
boolean containsKey(final K key);
public interface Maplet<K, V> extends BaseMaplet<K> {
@Nullable
V get(final K key);
void put(K key, V value);
void remove(K key);
Iterable<K> getKeys();
@Override
void close() throws IOException;
}

View File

@@ -3,20 +3,13 @@ package org.jetbrains.jps.dependency;
import org.jetbrains.annotations.NotNull;
import java.io.Closeable;
import java.io.IOException;
public interface MultiMaplet<K, V> extends Closeable {
boolean containsKey(K key);
public interface MultiMaplet<K, V> extends BaseMaplet<K> {
@NotNull
Iterable<V> get(K key);
void put(K key, @NotNull Iterable<? extends V> values);
void remove(K key);
void appendValue(K key, final V value);
default void appendValues(K key, @NotNull Iterable<? extends V> values) {
@@ -33,9 +26,4 @@ public interface MultiMaplet<K, V> extends Closeable {
}
}
@NotNull
Iterable<K> getKeys();
@Override
void close() throws IOException;
}

View File

@@ -56,4 +56,10 @@ public class CachingMaplet<K, V> implements Maplet<K, V> {
myCache.invalidateAll();
myDelegate.close();
}
@Override
public void flush() throws IOException {
myCache.invalidateAll();
myDelegate.flush();
}
}

View File

@@ -98,4 +98,10 @@ public class CachingMultiMaplet<K, V> implements MultiMaplet<K, V> {
myCache.invalidateAll();
myDelegate.close();
}
@Override
public void flush() throws IOException {
myCache.invalidateAll();
myDelegate.flush();
}
}

View File

@@ -3,6 +3,7 @@ package org.jetbrains.jps.dependency.impl;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.KeyDescriptor;
@@ -71,10 +72,11 @@ public final class Containers {
private static final int CACHE_SIZE = 512; // todo: make configurable?
private final String myRootDirPath;
private final PersistentStringEnumerator myStringTable;
private final List<Closeable> myMaps = new ArrayList<>();
private final List<BaseMaplet<?>> myMaps = new ArrayList<>();
private final Enumerator myEnumerator;
private final Function<Object, Object> myDataInterner;
private final LoadingCache<Object, Object> myInternerCache;
private final LowMemoryWatcher myMemWatcher;
PersistentMapletFactory(String rootDirPath) throws IOException {
myRootDirPath = rootDirPath;
@@ -90,10 +92,22 @@ public final class Containers {
return myStringTable.enumerate(str);
}
};
myInternerCache = Caffeine.newBuilder().maximumSize(2 * CACHE_SIZE).build(key -> key);
myInternerCache = Caffeine.newBuilder().maximumSize(CACHE_SIZE).build(key -> key);
myDataInterner = elem -> {
return elem instanceof Usage || elem instanceof String? myInternerCache.get(elem) : elem;
};
myMemWatcher = LowMemoryWatcher.register(() -> {
myInternerCache.invalidateAll();
myStringTable.force();
for (BaseMaplet<?> map : myMaps) {
try {
map.flush();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
@Override
@@ -118,6 +132,7 @@ public final class Containers {
@Override
public void close() {
myMemWatcher.stop();
Throwable ex = null;
for (Closeable container : Iterators.flat(myMaps, Iterators.asIterable(myStringTable))) {
try {

View File

@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.dependency.Maplet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -40,4 +41,9 @@ public final class MemoryMaplet<K, V> implements Maplet<K, V> {
public void close() {
myMap.clear();
}
@Override
public void flush() throws IOException {
// empty
}
}

View File

@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.dependency.MultiMaplet;
import org.jetbrains.jps.javac.Iterators;
import java.io.IOException;
import java.util.*;
import java.util.function.Supplier;
@@ -78,4 +79,9 @@ public final class MemoryMultiMaplet<K, V, C extends Collection<V>> implements M
public void close() {
myMap.clear();
}
@Override
public void flush() throws IOException {
// empty
}
}

View File

@@ -83,4 +83,8 @@ public final class PersistentMaplet<K, V> implements Maplet<K, V> {
myMap.close();
}
@Override
public void flush() throws IOException {
myMap.force();
}
}

View File

@@ -188,4 +188,8 @@ public final class PersistentMultiMaplet<K, V, C extends Collection<V>> implemen
}
}
@Override
public void flush() throws IOException {
myMap.force();
}
}

View File

@@ -8,6 +8,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FileCollectionFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.JpsBuildBundle;
import org.jetbrains.jps.builders.java.JavaBuilderUtil;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.incremental.BinaryContent;
@@ -38,6 +39,7 @@ final class OutputFilesSink implements OutputFileConsumer {
private final ModuleLevelBuilder.OutputConsumer myOutputConsumer;
private final Callbacks.Backend myMappingsCallback;
private final String myChunkName;
private final String myChunkOutputRootName;
private final Set<File> mySuccessfullyCompiled = FileCollectionFactory.createCanonicalFileSet();
OutputFilesSink(CompileContext context,
@@ -48,6 +50,7 @@ final class OutputFilesSink implements OutputFileConsumer {
myOutputConsumer = outputConsumer;
myMappingsCallback = callback;
myChunkName = "[" +chunkName + "]";
myChunkOutputRootName = "$" + chunkName.replaceAll("\\\\s", "_");
}
@Override
@@ -96,7 +99,10 @@ final class OutputFilesSink implements OutputFileConsumer {
// register in mappings any non-temp class file
try {
final ClassReader reader = new FailSafeClassReader(content.getBuffer(), content.getOffset(), content.getLength());
myMappingsCallback.associate(FileUtil.toSystemIndependentName(fileObject.getFile().getPath()), sourcePaths, reader, fileObject.isGenerated());
String fileName = JavaBuilderUtil.isDepGraphEnabled()?
myChunkOutputRootName + "/" + FileUtil.toSystemIndependentName(fileObject.getRelativePath()) :
FileUtil.toSystemIndependentName(fileObject.getFile().getPath());
myMappingsCallback.associate(fileName, sourcePaths, reader, fileObject.isGenerated());
}
catch (Throwable e) {
// need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation