Hi Tom,
Thanks for your observation and your code proposal; always welcome.
I have some concerns that the caching of non-existing classes could be exploited and bloat the cache. Maybe we’d need to use WeakHashMap (and/or soft references) instead?
I'm not sure why BaseX tries to load our xqm as Java Modules, but what I noticed is that Reflect.forName caches the positive case (i.e., the class is found), but not the negative case (i.e., the class is not found).
Sounds like an interesting finding; maybe there’s something we can optimize here. Could you possibly provide us a little self-contained example that demonstrates the behavior?
Thanks in advance, Christian
On Wed, Oct 17, 2018 at 9:53 AM Tom Rauchenwald (UNIFITS) tom.rauchenwald@unifits.com wrote:
Hi BaseX-Team,
when profiling some of our tests i found that we spend some time in Reflect.forName().
We have 2 xquery modules in the repo (we don't call java code directly).
I'm not sure why BaseX tries to load our xqm as Java Modules, but what I noticed is that Reflect.forName caches the positive case (i.e., the class is found), but not the negative case (i.e., the class is not found).
I've changed the code to cache the negative case as well (see below), and noticed an improvement of about 5 percent.
Our tests create and query loads of small databases, so this is maybe quite an artificial speedup.
I could provide a PR if this is a worthwhile improvement in your opinion (and if I'm not missing something obvious).
We're still on BaseX 8.7.6 in case that matters, as far as I could see the Code didn't change in BaseX 9.
Thanks,
Tom
Code:
public static Class<?> forName(final String name) throws ClassNotFoundException { Class<?> c = CLASSES.get(name);
if(c == null) { if (CLASSES.containsKey(name)) { throw new ClassNotFoundException(name); } else { try { c = Class.forName(name); } catch (ClassNotFoundException e) { CLASSES.put(name, null); throw e; } if (!Modifier.isPublic(c.getModifiers())) throw new ClassNotFoundException(name); CLASSES.put(name, c); } } return c;
}