performance improvements

lua-profiles
Mike Barry 2023-12-02 05:26:39 -05:00
rodzic dc951d1777
commit da29144103
4 zmienionych plików z 41 dodań i 53 usunięć

Wyświetl plik

@ -21,17 +21,20 @@ public class BenchmarkLua {
LuaEnvironment.loadScript(Arguments.of(), Path.of("planetiler-experimental/src/test/resources/power.lua"));
var feature = SimpleFeature.createFakeOsmFeature(GeoUtils.JTS_FACTORY.createPoint(new CoordinateXY(0, 0)), Map.of(),
"", "", 1, List.of());
int batch = 1_000_000;
var fc = new FeatureCollector.Factory(PlanetilerConfig.defaults(), Stats.inMemory());
for (int i = 0; i < 1_000; i++) {
for (int i = 0; i < batch; i++) {
env.profile.processFeature(feature, fc.get(feature));
}
long start = System.currentTimeMillis();
int num = 2_000_000;
for (int i = 0; i < num; i++) {
env.profile.processFeature(feature, fc.get(feature));
}
int num = 0;
do {
for (int i = 0; i < batch; i++) {
env.profile.processFeature(feature, fc.get(feature));
}
num += batch;
} while (System.currentTimeMillis() - start < 1_000);
long end = System.currentTimeMillis();
System.err.println("took " + (end - start) + "ms " +
Format.defaultInstance().numeric(num / ((end - start) / 1000.0)) + " features/sec");
System.err.println(Format.defaultInstance().numeric(num / ((end - start) / 1000.0)) + " calls/sec");
}
}

Wyświetl plik

@ -282,7 +282,9 @@ public class CoerceLuaToJava {
}
}
private static final Map<Class<?>, Map<Class<?>, Integer>> inheritanceLevelsCache = new ConcurrentHashMap<>();
private static final Map<ClassPair, Integer> inheritanceLevelsCache = new ConcurrentHashMap<>();
private record ClassPair(Class<?> baseClass, Class<?> subclass) {}
/**
* Determine levels of inheritance between a base class and a subclass
@ -296,11 +298,9 @@ public class CoerceLuaToJava {
return SCORE_UNCOERCIBLE;
if (baseclass == subclass)
return 0;
Map<Class<?>, Integer> map = inheritanceLevelsCache.get(baseclass);
if (map == null) {
map = inheritanceLevelsCache.computeIfAbsent(baseclass, k -> new ConcurrentHashMap<>());
}
Integer result = map.get(subclass);
// planetiler change: cache result of this value to improve performance
ClassPair key = new ClassPair(baseclass, subclass);
Integer result = inheritanceLevelsCache.get(key);
if (result != null) {
return result;
}
@ -308,7 +308,8 @@ public class CoerceLuaToJava {
Class<?>[] ifaces = subclass.getInterfaces();
for (Class<?> iface : ifaces)
min = Math.min(min, inheritanceLevels(baseclass, iface) + 1);
map.put(subclass, min);
// best-effort cache, might end up computing a few times but that's ok
inheritanceLevelsCache.put(key, min);
return min;
}

Wyświetl plik

@ -64,11 +64,11 @@ class JavaClass extends JavaInstance {
static final LuaValue NEW = valueOf("new");
private final Map<LuaValue, Field> fields;
private final Map<LuaValue, LuaValue> methods;
private final Map<LuaValue, Getter> getters;
private final Map<LuaValue, Setter> setters;
private final Map<LuaValue, Class<?>> innerclasses;
private final Map<LuaValue, Field> fields = new HashMap<>();
private final Map<LuaValue, LuaValue> methods = new HashMap<>();
private final Map<LuaValue, Getter> getters = new HashMap<>();
private final Map<LuaValue, Setter> setters = new HashMap<>();
private final Map<LuaValue, Class<?>> innerclasses = new HashMap<>();
public final boolean bindMethods;
static JavaClass forClass(Class<?> c) {
@ -85,20 +85,16 @@ class JavaClass extends JavaInstance {
this.jclass = this;
this.bindMethods = c.isAnnotationPresent(LuaBindMethods.class);
// planetiler change: compute these maps eagerly
fields = computeFields();
var result = computeMethods();
methods = result.methods;
getters = result.getters;
setters = result.setters;
innerclasses = computeInnerClasses();
computeFields();
computeMethods();
computeInnerClasses();
}
private Map<LuaValue, Field> computeFields() {
Map<LuaValue, Field> tmpFields = new HashMap<>();
Field[] f = ((Class<?>) m_instance).getFields();
for (Field fi : f) {
if (Modifier.isPublic(fi.getModifiers())) {
tmpFields.put(LuaValue.valueOf(fi.getName()), fi);
fields.put(LuaValue.valueOf(fi.getName()), fi);
try {
if (!fi.isAccessible()) {
fi.setAccessible(true);
@ -109,14 +105,11 @@ class JavaClass extends JavaInstance {
}
// planetiler change: add snake_case aliases for camelCase methods
putAliases(tmpFields);
return Map.copyOf(tmpFields);
putAliases(fields);
return fields;
}
private Methods computeMethods() {
Map<LuaValue, LuaValue> tmpMethods = new HashMap<>();
Map<LuaValue, Getter> tmpGettters = new HashMap<>();
Map<LuaValue, Setter> tmpSetters = new HashMap<>();
private void computeMethods() {
Map<String, List<JavaMethod>> namedlists = new HashMap<>();
Class<?> clazz = (Class<?>) m_instance;
Set<String> recordComponents =
@ -129,9 +122,9 @@ class JavaClass extends JavaInstance {
// also allow record components to be accessed as properties
if ((recordComponents.contains(name) || mi.isAnnotationPresent(LuaGetter.class)) &&
mi.getParameterCount() == 0) {
tmpGettters.put(LuaString.valueOf(name), new Getter(mi));
getters.put(LuaString.valueOf(name), new Getter(mi));
} else if (mi.isAnnotationPresent(LuaSetter.class)) {
tmpSetters.put(LuaString.valueOf(name), new Setter(mi, mi.getParameterTypes()[0]));
setters.put(LuaString.valueOf(name), new Setter(mi, mi.getParameterTypes()[0]));
}
namedlists.computeIfAbsent(name, k -> new ArrayList<>()).add(JavaMethod.forMethod(mi));
}
@ -147,10 +140,10 @@ class JavaClass extends JavaInstance {
case 0:
break;
case 1:
tmpMethods.put(NEW, list.get(0));
methods.put(NEW, list.get(0));
break;
default:
tmpMethods.put(NEW,
methods.put(NEW,
JavaConstructor.forConstructors(list.toArray(JavaConstructor[]::new)));
break;
}
@ -161,31 +154,22 @@ class JavaClass extends JavaInstance {
LuaValue luaMethod = classMethods.size() == 1 ?
classMethods.get(0) :
JavaMethod.forMethods(classMethods.toArray(JavaMethod[]::new));
tmpMethods.put(LuaValue.valueOf(name), luaMethod);
methods.put(LuaValue.valueOf(name), luaMethod);
}
// planetiler change: add snake_case aliases for camelCase methods
putAliases(tmpMethods);
putAliases(tmpGettters);
putAliases(tmpSetters);
return new Methods(
Map.copyOf(tmpMethods),
Map.copyOf(tmpGettters),
Map.copyOf(tmpSetters)
);
putAliases(methods);
putAliases(getters);
putAliases(setters);
}
record Methods(Map<LuaValue, LuaValue> methods, Map<LuaValue, Getter> getters, Map<LuaValue, Setter> setters) {}
private Map<LuaValue, Class<?>> computeInnerClasses() {
Map<LuaValue, Class<?>> result = new HashMap<>();
private void computeInnerClasses() {
Class<?>[] c = ((Class<?>) m_instance).getClasses();
for (Class<?> ci : c) {
String name = ci.getName();
String stub = name.substring(Math.max(name.lastIndexOf('$'), name.lastIndexOf('.')) + 1);
result.put(LuaValue.valueOf(stub), ci);
innerclasses.put(LuaValue.valueOf(stub), ci);
}
return Map.copyOf(result);
}
private <T> void putAliases(Map<LuaValue, T> map) {

Wyświetl plik

@ -124,7 +124,7 @@ class JavaInstance extends LuaUserdata {
public LuaValue get(LuaValue key) {
// planetiler change: allow lists to be accessed as tables
if (key.isnumber() && m_instance instanceof List<?> c) {
if (m_instance instanceof List<?> c) {
int idx = key.toint();
return idx <= 0 || idx > c.size() ? LuaValue.NIL : CoerceJavaToLua.coerce(c.get(idx - 1));
}