Community
Participate
Working Groups
1. Our products have many logical structures. 2. When debugging a large application, like a web server, or another instance of Eclipse, etc, we find that expanding a variable from the variables view is extremely slow if both logical structures and show references are turned on in the Variables View. Here's some timing information when show references is turned on: Logical Structures On Logical Structures Off Dual Core ~ 25 seconds ~ 1.5 seconds Single CPU ~ 45 seconds ? Slow Linux ~ 8 minutes 3 seconds When logical structures are turned on, I see that there are a bunch of JdwpCommandPacket.VM_CLASSES_BY_SIGNATURErequest sent, and they seem be time consuming. Doing a little more digging, I see these requests are a result of each of the logical structure type delegates having their providesLogicalStructure(IValue value) method being called. They all seem to call IJavaobject.getJavaType(), which results in the JdwpCommandPacket.VM_CLASSES_BY_SIGNATURErequest. I see that the IJavaObject is really a JDIReferenceListValue. The getJavaType() method of JDIReferenceListValue does not cache its value, so for every logical structure type delegate, this same JDIReferenceListValue.getJavaType() call results in a JdwpCommandPacket.VM_CLASSES_BY_SIGNATURErequest. I added caching to the JDIReferenceListValue.getJavaType() method, and the expansion time for the references node dropped to ~1.5 seconds, which is the same as when logical structures is not turned on. Is there some reason that the getJavaType() method should not be caching the result? If not, would it be possible to get this change into Eclipse 3.4? This is my caching version of JDIReferenceListValue.getJavaType() : public IJavaType getJavaType() throws DebugException { if (fJavaType == null) { IJavaType[] javaTypes = getJavaDebugTarget().getJavaTypes(getReferenceTypeName()); if (javaTypes.length > 0) { // return javaTypes[0]; fJavaType = javaTypes[0]; } } // return null; return fJavaType; } Here's some timing information when this fix is applied: Logical Structures On Dual Core 1.5 seconds Single CPU 3 seconds Slow Linux 4 seconds We can try to optimize our code in our logical structures delegate. Our experiments show that we can only reduce the time to expand variables by half. We were not able to reduce it down to the "seconds" range.
Created attachment 103436 [details] patch This patch does something similar to the suggested fix, but caches the type in the constructor (similar to code in JDIAllInstancesValue).
Philippe, would you agree to this performance fix in 3.4? It turns out that we have the same code to make the "all instances" feature faster, but we did not extend the pattern to the "all references" feature. The fix is small and well understood. Although this is not a regression, the fix dramatically improves performance for large collections of references.
Given it is critical, and we have a good fix at hand with drastic performance improvements, I would take it for 3.4.0.
Question: wouldn't it be more beneficial to manage a type cache in a more global manner, rather than caching individual types on JDIReferenceListValue ?
(In reply to comment #4) > Question: wouldn't it be more beneficial to manage a type cache in a more > global manner, rather than caching individual types on > JDIReferenceListValue ? We don't maintain a cache of all loaded types. We retrieve types lazily as requested by the client. Once a type is retrieved, its information is cached. However, in this case the implementation was using an API to dynamically retrieve all types with a known name ("java.lang.Object[]"). This implementation of "list value" is only used by the Java 6 "show all references feature". It's a facade representing a value which is an array of objects referencing some other object.
+1
Applied patch.
Verified.