在我的应用程序中obj.getClass().isArray()
被频繁调用并成为应用程序的瓶颈
如果对象是数组,我想在运行时有效地检查。
原始数组和对象数组应返回true
我可以想象的方式是instanceof
所有原始数组,但不能处理类似int [] []的类型。该应用程序用作lib,因此我无法列出所有类型
有什么线索吗?
答案 0 :(得分:8)
我刚刚完成的基准测试得出以下结果:
{s instanceof Object[]} spends 44ms
{s.getClass().getName().charAt(0) == '['} spends 58ms
{s.getClass().isArray()} spends 303ms
使用Benchmark.java进行基准测试,使用Main.java调用。
在上述基准测试中讨论了final
变量的使用后,请使用本地变量查看新结果:
{s instanceof Object[]} spends 83ms
{s.getClass().getName().charAt(0) == '['} spends 93ms
{s.getClass().isArray()} spends 354ms
即使持续时间都有点长(有趣的顺便说一句),它们的顺序也已保留。
然后使用这个新的Main.java调用Benchmark.java。
使用另一个Main.java调用的原始数组:
{a instanceof int[]} spends 71ms
{a.getClass().getName().charAt(0) == '['} spends 82ms
{a.getClass().isArray()} spends 340ms
结果顺序仍然相同。
答案 1 :(得分:7)
isArray()
是在运行时检查对象是否是数组实例的最有效方法。如果性能有问题,您可以使用以下方法之一来解决它:
isArray()
的结果在编译时是已知的。isArray()
的值,因此只需要调用一次。答案 2 :(得分:2)
根据您的意见,我得出结论,在调查分析结果时,您可能会遇到解释性错误。您的探查器的方法级检测可能会严重削弱getClass()
和isArray()
次呼叫,同时对instanceof
表达式不感兴趣。换句话说,您可能正在测量探查器的测量开销。
此外,在快速基准测试中,我无法支持您的申请。我运行了以下非常愚蠢的测试:
public class Test {
public static void main(String[] args) {
final int rep = 10000000;
Object[] o = {
null,
1,
"x",
new Object[0],
new Object[0][],
new int[0],
new int[0][]
};
// "Warmup" to avoid potential JVM startup overhead
long x = 0;
for (int i = 0; i < rep; i++) {
x+=checkInstanceOf(o);
}
for (int i = 0; i < rep; i++) {
x+=checkIsArray(o);
}
for (int i = 0; i < rep; i++) {
x+=checkClassName(o);
}
// Actual test
long t1 = System.nanoTime();
for (int i = 0; i < rep; i++) {
x+=checkInstanceOf(o);
}
long t2 = System.nanoTime();
for (int i = 0; i < rep; i++) {
x+=checkIsArray(o);
}
long t3 = System.nanoTime();
for (int i = 0; i < rep; i++) {
x+=checkClassName(o);
}
long t4 = System.nanoTime();
System.out.println(t2 - t1);
System.out.println(t3 - t2);
System.out.println(t4 - t3);
}
private static int checkInstanceOf(Object[] o) {
int i = 0;
for (Object x : o) {
if (x instanceof Object[]) i++; // Perform some logic
else if (x instanceof boolean[]) i++; // to keep the compiler or
else if (x instanceof byte[]) i++; // the JVM from optimising
else if (x instanceof short[]) i++; // this code away
else if (x instanceof int[]) i++;
else if (x instanceof long[]) i++;
else if (x instanceof float[]) i++;
else if (x instanceof double[]) i++;
else if (x instanceof char[]) i++;
}
return i;
}
private static int checkIsArray(Object[] o) {
int i = 0;
for (Object x : o) {
if (x != null && x.getClass().isArray()) i++;
}
return i;
}
private static int checkClassName(Object[] o) {
int i = 0;
for (Object x : o) {
if (x != null && x.getClass().getName().charAt(0) == '[') i++;
}
return i;
}
}
我得到了:
394433000 // instanceof
110655000 // getClass().isArray()
396039000 // getClass().getName().charAt(0) == '['
因此,通常声明getClass().isArray()
要比instanceof
一套彻底的{{1}}检查要慢。当然,有很多不同的方法来重写我的测试,但你明白了。