EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-based tools run fasterEce2013 optimizing performance
- 16. Build workspace (16%)...
taken from a different case
what is exactly going on under the hood?
•
•
the Spring-specific 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-specific 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.)
- 20. Action 1: Configure your Eclipse wisely
max heap size
build workspace
-Xmx768m
30min
!
!
!
!
!
!
-Xmx1024m
~7min
- 21. Action 2: Reduce garbage
and memory usage in general
•
•
•
String.format creates a lot of garbage
called many many times
most of the time with exactly one argument
- 22. Action 2: Reduce garbage
and memory usage in general
public Set<IBean> getBeans() {
Set<IBean> allBeans = new LinkedHashSet<IBean>(beans.values());
for (IBeansImport beansImport : imports) {
for (IBeansConfig bc : beansImport.getImportedBeansConfigs()) {
allBeans.addAll(bc.getBeans());
}
}
return Collections.unmodifiableSet(allBeans);
}
- 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 (IBeansConfig bc : beansImport.getImportedBeansConfigs()) {
allBeans.addAll(bc.getBeans());
}
}
return Collections.unmodifiableSet(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-specific builder: sloooooow...
- 26. watch out for visitors
class ResourceDeltaVisitor implements IResourceDeltaVisitor {
}
!
public boolean visit(IResourceDelta aDelta) throws CoreException {
IResource resource = aDelta.getResource();
if (resource instanceof IFile) {
checkResource(resource);
}
return true;
}
- 27. watch out for visitors
class ResourceDeltaVisitor implements IResourceDeltaVisitor {
}
!
public boolean visit(IResourceDelta aDelta) throws CoreException {
IResource resource = aDelta.getResource();
if (resource instanceof IFile) {
checkResource(resource);
}
return true;
}
•
•
•
this might be called many many times
take care to make this simple and fast
not allowed to iterate over collections
- 28. watch out for visitors
class ResourceDeltaVisitor implements IResourceDeltaVisitor {
}
!
•
public boolean visit(IResourceDelta aDelta) throws CoreException {
IResource resource = aDelta.getResource();
if (resource instanceof IFile) {
checkResource(resource);
}
return true;
}
•
•
•
this might be called many many times
take care to make this simple and fast
not allowed to iterate over collections
in our case:
• takes a look at individual IResource objects
• identify the defined types
• iterate over all defined beans and check for type
dependency
- 29. 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
- 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
- 32. 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
Lessons Learned
reading bytecode is super super fast
finding the bytecode on the classpath is super slow
- 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
- 37. Q&A
!
and thank you for your attention
Martin Lippert
Principal Software Engineer - Pivotal
mlippert@gopivotal.com
@martinlippert