Why is this method a hot spot?
java, optimization, performance, visualvm
Solution
I figured out that this method looked like a hotspot because VisualVM was being instructed to ignore methods from the JRE in its profiling. The time being spent in those "ignored" methods was (ostensibly) being rolled into the self time of the topmost non-ignored entry of the call stack.
Below is the settings screen in VisualVM, including the "Do not profile packages" setting that was making the data wrong. To adjust the "ignore class" settings, you have to (1) click the "Settings" checkbox highlighted in red, then (2) adjust the classes setting highlighted in blue.
Depending on what you're doing, it probably makes sense at least not to ignore the `java.*` and `javax.*` packages.
Problem
I'm writing a (simple!) linear algebra library. In the implementation of matrix multiplication, a VisualVM performance sample is telling me that the algorithm spends 85% of its time ("self time", specifically) in the following method when multiplying large matrices (5k x 120k): ``` public double next() { double result; if(hasNext()) result = vis[i++].next(); else throw new IllegalStateException("No next value"); return result; } ``` Without going into too much detail (sorry, I can't share more code), this method is the `next()` method of an "iterator" for the matrix. (You can think of the class this method lives in as a row iterator made up of individual column iterators, which are stored in `vis`.) I'm not surprised that this method gets called a lot since it's an iterator, but I am surprised that the program spends a lot of its time in this method. This method doesn't do too much, so why is it spending its time here? Here are the specific questions I'm asking: - Is there some "gotcha" of VisualVM I'm hitting? For example, could the JIT be confusing VisualVM in some way that's causing VisualVM to attribute time to the wrong method? - Why would the program be spending its time here? The method just doesn't do too much. In particular, I don't think cache effects explain this problem because the `vis` array is much smaller than the data of the matrices being multiplied. In case it's useful, here's a jad disassembly of the method I pasted above: ``` 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 } ``` Thanks in advance for your help guys!