我正在写一个(简单!)线性代数库。在矩阵乘法的实现中,一个VisualVM性能样本告诉我,当乘以大型矩阵 (5k x 120k) 时,该算法在以下方法中花费了 85% 的时间(特别是“自身时间”):
public double next() {
double result;
if(hasNext())
result = vis[i++].next();
else
throw new IllegalStateException("No next value");
return result;
}
无需赘述(抱歉,我无法分享更多代码),此方法是next()
矩阵的“迭代器”方法。(你可以把这个方法所在的类想象成一个行迭代器,它由存储在vis
.该程序在这种方法上花费了大量时间。这种方法做的不多,为什么要花时间在这里呢?
以下是我要问的具体问题:
- 我遇到了一些 VisualVM 的“陷阱”吗?例如,JIT 是否会以某种方式混淆 VisualVM,从而导致 VisualVM 将时间归因于错误的方法?
- 为什么程序会花时间在这里?该方法只是没有做太多。特别是,我认为缓存效应不能解释这个问题,因为
vis
数组比被相乘的矩阵的数据要小得多。
如果它有用,这是我上面粘贴的方法的jad反汇编:
public double next()
{
double result;
if(hasNext())
//* 0 0:aload_0
//* 1 1:invokevirtual #88 <Method boolean hasNext()>
//* 2 4:ifeq 32
result = vis[i++].next();
// 3 7:aload_0
// 4 8:getfield #42 <Field VectorIterator[] vis>
// 5 11:aload_0
// 6 12:dup
// 7 13:getfield #28 <Field int i>
// 8 16:dup_x1
// 9 17:iconst_1
// 10 18:iadd
// 11 19:putfield #28 <Field int i>
// 12 22:aaload
// 13 23:invokeinterface #72 <Method double VectorIterator.next()>
// 14 28:dstore_1
else
//* 15 29:goto 42
throw new IllegalStateException("No next value");
// 16 32:new #89 <Class IllegalStateException>
// 17 35:dup
// 18 36:ldc1 #91 <String "No next value">
// 19 38:invokespecial #93 <Method void IllegalStateException(String)>
// 20 41:athrow
return result;
// 21 42:dload_1
// 22 43:dreturn
}
提前感谢您的帮助!