Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

8,476 views

Published on

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.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

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

  1. 1. Martin Lippert Principal Software Engineer - Pivotal mlippert@gopivotal.com @martinlippert Optimizing Performance how to make your Eclipsebased tools run faster
  2. 2. Every developer benefits from better performance
  3. 3. Find out where the problem is... failblog.com
  4. 4. Measure !!!
  5. 5. VisualVM ! Free Easy to use comes as part of the JDK extremely useful to capture data remotely
  6. 6. YourKit used for comprehensive analysis various options and ways to track down issues $$$ ! ! alternative: JProfiler $$$
  7. 7. the case
  8. 8. trivial: expensive calls inside loops
  9. 9. findFilesForLocationURI(..) is slow step 1: fix this in the Eclipse platform
  10. 10. findFilesForLocationURI(..) is slow step 2: cache results if that makes sense
  11. 11. findFilesForLocationURI(..) is slow step 3: if you can‘t avoid massive use of this,
 optimize for the most likely case
  12. 12. Build workspace (16%)... why is the build taking soooooo long... ???
  13. 13. Build workspace (16%)...
  14. 14. Build workspace (16%)... taken from a different case what is exactly going on under the hood?
  15. 15. Build workspace (16%)... taken from a different case what is exactly going on under the hood? • the Spring-specific builder: sloooooow...
  16. 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. 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. 18. But wait a moment...
  19. 19. But wait a moment... what is this ?!?
  20. 20. Action 1: Configure your Eclipse wisely max heap size build workspace -Xmx768m 30min ! ! ! ! ! ! -Xmx1024m ~7min
  21. 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. 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. 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. 24. Now back to the details of this… • the Spring-specific builder: sloooooow...
  25. 25. O(n) matters for scalability
  26. 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. 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. 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. 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. 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. 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. 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. 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. 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. 35. A different approach Proposal mock-up – not an actual program from Chris Laffras talk on Eclipse performance
  36. 36. 1.Measure 2.Optimize ! 3.Goto 1.
  37. 37. Q&A ! and thank you for your attention Martin Lippert Principal Software Engineer - Pivotal mlippert@gopivotal.com @martinlippert

×