I have old code with a lot of methods like long[] toLongArray(int[] array)
but for many different primitive types configurations (on both sides) and I just wonder if it is possible to make one generic method for this - without losing performance.
First I created simple method using MethodHandles for int[] -> long[] pair:
static final MethodHandle getIntElement = MethodHandles.arrayElementGetter(int[].class);
static final MethodHandle setLongElement = MethodHandles.arrayElementSetter(long[].class);
static long[] specializedMethodHandle(int[] array) throws Throwable {
long[] newArray = new long[array.length];
for (int i = 0; i < array.length; i++) getIntElement.invokeExact(newArray, i, (long) (int) setLongElement.invokeExact(array, i));
return newArray;
}
And it works great - same performance as manual loop, so I decided to make this generic:
static Map<Class<?>, MethodHandle> metHanGettersObj = Map.of(int[].class, MethodHandles.arrayElementGetter(int[].class).asType(MethodType.methodType(Object.class, Object.class, int.class)));
static Map<Class<?>, MethodHandle> metHanSettersObj = Map.of(long[].class, MethodHandles.arrayElementSetter(long[].class).asType(MethodType.methodType(void.class, Object.class, int.class, Object.class)));
static <F, T> T genericMethodHandleObject(Class<T> to, F array) throws Throwable {
int length = Array.getLength(array);
Object newArray = Array.newInstance(to.getComponentType(), length);
MethodHandle getElement = metHanGettersObj.get(array.getClass());
MethodHandle setElement = metHanSettersObj.get(to);
for (int i = 0; i < length; i++) setElement.invokeExact(newArray, i, getElement.invokeExact(array, i));
return (T) newArray;
}
But this works much much slower, for my example array of 500000 elements it was over 15x slower.
What is interesting CompiledScript made with Nashorn javascript engine is around 20% faster than this code. (simple copy loop inside)
So I wonder if someone know other way to do this? I will probably not use that anywhere as it is starting to be too "hacky" but now I just need to know if it is possible at all - as no generic method with method handles works fine, so why this one is that slow, and is it possible to make it faster?