【发布时间】:2018-12-03 05:05:41
【问题描述】:
我的旧代码有很多方法,比如long[] toLongArray(int[] array),但是对于许多不同的原始类型配置(两边),我只是想知道是否有可能为此创建一种通用方法 - 而不会损失性能。
首先,我使用 MethodHandles 为 int[] -> long[] 对创建了简单的方法:
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;
}
而且效果很好 - 与手动循环的性能相同,因此我决定将其设为通用:
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;
}
但这工作要慢得多,对于我的 500000 个元素的示例数组,它慢了 15 倍以上。
有趣的是,使用 Nashorn javascript 引擎制作的 CompiledScript 比这段代码快 20% 左右。 (里面有简单的复制循环)
所以我想知道是否有人知道其他方法可以做到这一点?我可能不会在任何地方使用它,因为它开始太“hacky”了,但现在我只需要知道它是否可能 - 因为没有带有方法句柄的通用方法可以正常工作,所以为什么这个方法这么慢,并且有没有可能让它更快?
【问题讨论】:
-
您如何对此进行基准测试?
-
“可能为此创建一个通用方法”不,因为没有有用的通用超类型。您所做的任何事情都将是反射性的,并且其性能将低于单个方法。
-
@JornVernee 是的,否则我不知道它是否更慢。 (JMH 中的简单基准)
-
@AndyTurner MethodHandles 可以和普通代码一样快 - 但只有在并非在所有情况下都正确使用时,在某些地方 lambda 工厂 + 方法句柄会有所帮助。但到目前为止,我找不到更好的方法。但是,如果您将使用反射和
Array类来执行此操作,它将比此 MethodHandle 版本慢 15 倍 - 所以这已经比反射更好。因为方法句柄不仅仅是反射。 -
不认真,您如何对此进行基准测试?
标签: java performance methodhandle