SlideShare a Scribd company logo
Martin Lippert	

Principal Software Engineer - Pivotal	

mlippert@gopivotal.com	

@martinlippert

Optimizing	

Performance	

how to make your Eclipsebased tools run faster
Every developer benefits
from better performance
Find out where the problem is...

failblog.com
Measure !!!
VisualVM
!

Free	

Easy to use	

comes as part of the JDK	

extremely useful to capture data remotely
YourKit

used for comprehensive analysis	

various options and ways to track down issues	

$$$	

!
!

alternative:	


JProfiler
$$$
the case
trivial: expensive calls inside loops
findFilesForLocationURI(..) is slow

step 1: fix this in the Eclipse platform
findFilesForLocationURI(..) is slow

step 2: cache results if that makes sense
findFilesForLocationURI(..) is slow
step 3: if you can‘t avoid massive use of this,

optimize for the most likely case
Build workspace (16%)...

why is the build taking	

soooooo long... ???
Build workspace (16%)...
Build workspace (16%)...
taken from a different case

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

what is exactly going on under the hood?
•

the Spring-specific builder: sloooooow...
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...
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.)
But wait a moment...
But wait a moment...

what is this ?!?
Action 1: Configure your Eclipse wisely

max heap size

build workspace

-Xmx768m

30min

!

!

!

!

!

!

-Xmx1024m

~7min
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
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);
}
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
Now back to the details of this…

•

the Spring-specific builder: sloooooow...
O(n)
matters for scalability
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;
}
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
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
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
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
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
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
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	

!

...
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
A different approach
Proposal mock-up – not an actual program

from Chris Laffras talk on Eclipse performance
1.Measure
2.Optimize
!

3.Goto 1.
Q&A
!
and thank you for your attention

Martin Lippert	

Principal Software Engineer - Pivotal	

mlippert@gopivotal.com	

@martinlippert

More Related Content

EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-based tools run fasterEce2013 optimizing performance

  • 1. Martin Lippert Principal Software Engineer - Pivotal mlippert@gopivotal.com @martinlippert Optimizing Performance how to make your Eclipsebased tools run faster
  • 2. Every developer benefits from better performance
  • 3. Find out where the problem is... failblog.com
  • 5. VisualVM ! Free Easy to use comes as part of the JDK extremely useful to capture data remotely
  • 6. YourKit used for comprehensive analysis various options and ways to track down issues $$$ ! ! alternative: JProfiler $$$
  • 9. findFilesForLocationURI(..) is slow step 1: fix this in the Eclipse platform
  • 10. findFilesForLocationURI(..) is slow step 2: cache results if that makes sense
  • 11. findFilesForLocationURI(..) is slow step 3: if you can‘t avoid massive use of this,
 optimize for the most likely case
  • 12. Build workspace (16%)... why is the build taking soooooo long... ???
  • 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-specific builder: sloooooow...
  • 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.)
  • 18. But wait a moment...
  • 19. But wait a moment... what is this ?!?
  • 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
  • 35. A different approach Proposal mock-up – not an actual program from Chris Laffras talk on Eclipse performance
  • 37. Q&A ! and thank you for your attention Martin Lippert Principal Software Engineer - Pivotal mlippert@gopivotal.com @martinlippert