Over the past year we worked a lot on the performance of the Spring-related tooling for Eclipse. In this session we present our lessons learned. We show how we identified Eclipse-specific performance bottlenecks, how we solved and/or worked around them, and demo the tools we used for this.
We will walk through a number of real cases that we solved and discuss how we solved them. For example, we will discuss how we improved build times of Spring projects by a factor of 10, and reduced memory consumption at the same time. All of the presented cases are not specific to Spring tooling, so that the solutions are directly applicable to other Eclipse plugins. The areas that we will cover include using the JDT API, processing types and type hierarchies in source and class files, accessing resources and file content, scaling some algorithms, and more.

14.
Build workspace (16%)...
taken from a different case
what is exactly going on under the hood?

15.
Build workspace (16%)...
taken from a different case
what is exactly going on under the hood?
•
the Spring-speciﬁc builder: sloooooow...

16.
Build workspace (16%)...
taken from a different case
what is exactly going on under the hood?
•
•
the Spring-speciﬁc builder: sloooooow...
the Maven project builder: slooooow...
•
the WTP JS builder: slooooow...

17.
Build workspace (16%)...
taken from a different case
what is exactly going on under the hood?
•
•
the Spring-speciﬁc builder: sloooooow...
the Maven project builder: slooooow...
•
the WTP JS builder: slooooow...
•
the core implementation is ultra fast (compiling
Java, for example, but also reconciling, invoking
content assist, etc.)

23.
Action 2: Reduce garbage
and memory usage in general
new set with copied content
public Set<IBean> getBeans() {
Set<IBean> allBeans = new LinkedHashSet<IBean>(beans.values());
for (IBeansImport beansImport : imports) {
for (IBeansConﬁg bc : beansImport.getImportedBeansConﬁgs()) {
allBeans.addAll(bc.getBeans());
}
}
return Collections.unmodiﬁableSet(allBeans);
}
recursive call
•
•
imagine this is called with deep recursion
but since the method looks quite innocent, it is called
many times while doing the build

24.
Now back to the details of this…
•
the Spring-speciﬁc builder: sloooooow...

30.
the case: type checks
Set<IType> typesToCheck = new HashSet<IType>();
IType[] types = cu.getAllTypes();
for (IType type : types) {
IType[] subTypes = type.newTypeHierarchy(monitor).getAllSubtypes(type);
if (subTypes != null && subTypes.length > 0) {
typesToCheck.addAll(Arrays.asList(subTypes));
}
}
!
!
!
loop over beans and check each bean type whether it is contained in
typesToCheck
•
•
•
asking a type for its hierarchy is slow
cached, but only for a limited number of hierarchies
doing this for all resources of a build can take a very long time

31.
instead:
we built our own type hierarchy engine
TypeHierarchyEngine
it reads bytecode (only type information)
it walks up the super classes and interfaces
it caches already loaded type information

33.
What is designed to be fast?
Reconciling
Be extremely careful when implementing a
reconcile participant
!
Content-Assist
Has to be fast
Don‘t do anything if its not your job
!
...

34.
Startup time is important
(even if you start Eclipse just once a day)
!
!
Don‘t start
all your bundles and do stuff at startup
!
Do caching
(Equinox Weaving, for example)
!
Uninstall bundles
to get rid of things you don‘t need

35.
A different approach
Proposal mock-up – not an actual program
from Chris Laffras talk on Eclipse performance