diff --git a/planetiler-benchmarks/src/main/java/com/onthegomap/planetiler/benchmarks/BenchmarkLua.java b/planetiler-benchmarks/src/main/java/com/onthegomap/planetiler/benchmarks/BenchmarkLua.java index 712f8c6d..0cf4d51b 100644 --- a/planetiler-benchmarks/src/main/java/com/onthegomap/planetiler/benchmarks/BenchmarkLua.java +++ b/planetiler-benchmarks/src/main/java/com/onthegomap/planetiler/benchmarks/BenchmarkLua.java @@ -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"); } } diff --git a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java index de6e2bc0..54f61734 100644 --- a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java +++ b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java @@ -282,7 +282,9 @@ public class CoerceLuaToJava { } } - private static final Map, Map, Integer>> inheritanceLevelsCache = new ConcurrentHashMap<>(); + private static final Map 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, 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; } diff --git a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java index 6dd44c13..93e7f5ef 100644 --- a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java +++ b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java @@ -64,11 +64,11 @@ class JavaClass extends JavaInstance { static final LuaValue NEW = valueOf("new"); - private final Map fields; - private final Map methods; - private final Map getters; - private final Map setters; - private final Map> innerclasses; + private final Map fields = new HashMap<>(); + private final Map methods = new HashMap<>(); + private final Map getters = new HashMap<>(); + private final Map setters = new HashMap<>(); + private final Map> 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 computeFields() { - Map 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 tmpMethods = new HashMap<>(); - Map tmpGettters = new HashMap<>(); - Map tmpSetters = new HashMap<>(); + private void computeMethods() { Map> namedlists = new HashMap<>(); Class clazz = (Class) m_instance; Set 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 methods, Map getters, Map setters) {} - - private Map> computeInnerClasses() { - Map> 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 void putAliases(Map map) { diff --git a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaInstance.java b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaInstance.java index 82e450e1..8f20998e 100644 --- a/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaInstance.java +++ b/planetiler-experimental/src/main/java/org/luaj/vm2/lib/jse/JavaInstance.java @@ -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)); }