Reduce memory consumption in dependency analyzer

This commit is contained in:
Alexey Andreev 2024-03-18 16:21:12 +01:00
parent 287333b54e
commit 6e416c11d7
2 changed files with 68 additions and 11 deletions

View File

@ -15,13 +15,16 @@
*/
package org.teavm.dependency;
import com.carrotsearch.hppc.IntIntHashMap;
import java.util.BitSet;
import org.teavm.common.OptionalPredicate;
class SuperClassFilter implements DependencyTypeFilter {
private static final int SMALL_CACHE_THRESHOLD = 16;
private OptionalPredicate<String> predicate;
private BitSet knownTypes = new BitSet();
private BitSet cache = new BitSet();
private IntIntHashMap smallCache;
private BitSet knownTypes;
private BitSet cache;
SuperClassFilter(DependencyAnalyzer dependencyAnalyzer, DependencyType superType) {
predicate = dependencyAnalyzer.getClassHierarchy().getSuperclassPredicate(superType.getName());
@ -29,12 +32,38 @@ class SuperClassFilter implements DependencyTypeFilter {
@Override
public boolean match(DependencyType type) {
if (knownTypes.get(type.index)) {
return cache.get(type.index);
if (knownTypes != null) {
if (knownTypes.get(type.index)) {
return cache.get(type.index);
}
boolean result = predicate.test(type.getName(), false);
knownTypes.set(type.index);
cache.set(type.index, result);
return result;
}
boolean result = predicate.test(type.getName(), false);
knownTypes.set(type.index);
cache.set(type.index, result);
return result;
if (smallCache == null) {
smallCache = new IntIntHashMap();
}
var result = smallCache.getOrDefault(type.index, -1);
if (result != -1) {
return result != 0;
}
var value = predicate.test(type.getName(), false);
smallCache.put(type.index, value ? 1 : 0);
if (smallCache.size() > SMALL_CACHE_THRESHOLD) {
knownTypes = new BitSet();
cache = new BitSet();
for (var entry : smallCache) {
knownTypes.set(entry.key);
if (entry.value != 0) {
cache.set(entry.key);
}
}
smallCache = null;
}
return value;
}
}

View File

@ -15,17 +15,21 @@
*/
package org.teavm.dependency;
import com.carrotsearch.hppc.IntHashSet;
import com.carrotsearch.hppc.IntSet;
import java.util.BitSet;
import org.teavm.model.CallLocation;
import org.teavm.model.MethodDescriptor;
class VirtualCallConsumer implements DependencyConsumer {
private static int SMALL_TYPES_THRESHOLD = 16;
private final MethodDescriptor methodDesc;
private final DependencyAnalyzer analyzer;
private final DependencyNode[] parameters;
private final DependencyNode result;
private final CallLocation location;
private final BitSet knownTypes = new BitSet();
private IntSet smallKnownTypes;
private BitSet knownTypes;
private DependencyGraphBuilder.ExceptionConsumer exceptionConsumer;
private DependencyTypeFilter filter;
private boolean isPolymorphic;
@ -43,16 +47,40 @@ class VirtualCallConsumer implements DependencyConsumer {
this.exceptionConsumer = exceptionConsumer;
}
private boolean addKnownType(int index) {
if (knownTypes != null) {
if (knownTypes.get(index)) {
return false;
} else {
knownTypes.set(index);
return true;
}
}
if (smallKnownTypes == null) {
smallKnownTypes = new IntHashSet();
}
if (smallKnownTypes.add(index)) {
if (smallKnownTypes.size() > SMALL_TYPES_THRESHOLD) {
knownTypes = new BitSet();
for (var cursor : smallKnownTypes) {
knownTypes.set(cursor.value);
}
smallKnownTypes = null;
}
return true;
}
return false;
}
@Override
public void consume(DependencyType type) {
if (!filter.match(type)) {
return;
}
if (knownTypes.get(type.index)) {
if (!addKnownType(type.index)) {
return;
}
knownTypes.set(type.index);
String className = type.getName();