views:

4034

answers:

9

What are your tricks / resources for performance tuning a grails app?

I'm developing my first serious grails application, and got the basic functionality to work, so now I'd like to make it go faster. There are some operations that should not take very long but do, and an one that I know can never be fast, but which takes too long even when I reduce its scope to the bare minimum.

I've enabled the hibernate cache and made all relations load eagerly (which should be better since the total amount of data is quite small), but this has had no noticeable effect.

I've tried to profile, but I need something more fine-grained than the grails profiler plugin and could get neither eclipse TPTP nor VisualVM to work. With the former I am not surprised since it's always been a godawfully overengineered mess, while VisualVM requires on-the-fly instrumentation that doesn't seem to work with Groovy.

So what can I do besides playing guessing games?

Edit: I ended up doing "printf-profiling" and found that most of the time was spent in 2 or 3 innocent lines of code that did some very simple calculations. Yeah, they were run a lot, but the same methods contained much more complex operations that were run just as much. The killer seems to have been division operations involving Groovy's implicit conversions to BigDecimal. After extracting those calculations into static Java methods that use float exclusively, execution times were down by 90%.

I'm still looking for a way to use a real profiler though, since that would have saved me hours of work narrowing down where to put manual timings while repeatedly restarting grails (slow) and running the operations in question (very slow - that's why asked this question after all).

A: 

you could do manual profiling - literally, littering printf statements (or use a logging framework!) with timestamps. i suppose you have a few areas that are suspected bottlenecks, so wrap around them:

long t0 = System.currentTimeMillis()
//your suspected slow code...
System.err.println("took "+(System.currentTimeMillis()-t0) +"ms")

that is the old fashion way, and it always works.

Chii
Why use system outs when you have log4j in the stack already? With log4j you can tune/route the logging with minimal effort.
Kevin Williams
I ended up using this, and I can answer: because you want results, not tuned and routed logging. I tried to use log4j, didn't work (I have no idea what I did wrong, and I don't care), used System.out, got results. Log4j adds complexity but no value for such a simple case.
Michael Borgwardt
yes, if its not for logging, log4j or any logging framework is overkill - because you are going to delete these lines of code after you've figured out the performance problems right?
Chii
+10  A: 

Here some things that I would do to grain performance in grails apps:

  • Upgrade to Grails 1.1/Groovy 1.6 (if you haven't already)
  • Compare performance in production mode (grails prod run-app, or run it as a war in the target servlet container)
  • Reduce work load on application server by fronting it with a lightweight http server that handles static resources (Apache httpd, lighttpd, squid) or use a CDN
    • Set appropriate Expires headers or use something like the ui-performance plugin
  • Increase Java heap space (-Xmx)
  • Make sure to use an optimal second level cache configuration
    • cache true should be included in all domain classes (in the mapping closure) (1) to take effect
    • use cache: 'read-only' or cache: 'nonstrict-read-write' where possible
    • use ehcache as caching provider and adjust the ehcache settings by creating a 'ehcache.xml' in the grails-app/conf directory (if database is the bottleneck, you could use a huge cache with overflowToDisk)
    • Use Query-caching for frequently used queries: eg. Book.findByTitleLikeAndAuthor('Foo%', 'Graeme Rocher', cache: true)
  • Identify bottlenecks of your code by simple timings (capturing System.currentTimeInMillis()) and logging
    • Cache this business-logic where possible (eg. with springcache plugin)
    • rewrite costly calculations it in Java
  • Use in-memory maps for lookups instead of repeated queries/complex queries
  • Use transactional services only when needed (static transactional = false)
  • Reduce view (gsp's) size/count (if you have large views) and introduce dynamic Ajax updates and/or JSON communication

(1)

class Book {
  ...
  static mapping = {
      cache true
  }
}
Siegfried Puchbauer
Much of it is sensible advice that I had already considered, but in the end, you really need to measure rather than guess, and a profiler makes this much quicker and easier than manual timings.
Michael Borgwardt
Profiling Groovy code generally isn't that useful as you might think. You probably need to know the internals of groovy very well to interpret the results, since meta method dispatch and things like that will consume a lot of time. AFAIK there is no groovy-aware profiler available, unfortunately.
Siegfried Puchbauer
I'd expect a good profiler to be useful anyway - you should be able to ignore/filter the groovy-internal stuff, and call graphs can show you where the calls that end up eating excessive internally actually come from.
Michael Borgwardt
Agreed. I've successfully used visualVM and YKJP with Grails apps (I've just successfully tried with Grails 1.1 and visualVM 1.1.1). What's the issue you're experiencing?
Siegfried Puchbauer
I now got visualVM to work; there were error messages about not being able to instrument classes, but unlike before I got some results after that.
Michael Borgwardt
+4  A: 

I'd recommend using perf4j for metrics gathering. A plugin for grails seems to be on the works, meanhwhile you can plug your own interceptor (see this for an example).

Miguel Ping
I've (finally) released the first version of the Grails Perf4J plugin: http://www.grails.org/plugin/perf4j
Daniel Rinser
Nice, I'll give it a try
Miguel Ping
+3  A: 

Besides what Siegfried mentioned, optimizing the UI also goes a long way when performance tunning any web app.

For that you use YSlow plugin together with other grails plugins such as UIPerformance

Xymor
Optimizing the UI is totally irrelevant when (as in my case) you have pages that involve complex calculations that take several minutes to complete and the expected number of concurrent users is in the single digits. Still, that plugin looks very interesting - will keep it in mind for more conventional webapps.
Michael Borgwardt
I completely agree, but you didn't specify those contraints. It's really up to what purpose you're app will serve, but most web-apps gain a lot of performance points when the UI is properly optimized, which is often neglected.
Xymor
+3  A: 

I eventually got visualVM to work and, using it, found that one page that was unexpectedly slow to load took most of its time in a parsing step of the sitemesh component of grails.

This was a very large (500KB) page with a huge number of identical (except for the binding and the initial value) comboboxes - apparently sitemesh will parse and modify the already complete GSP.

So far, my remedy for this (which I am not too happy with) is to use JavaScript to render those comboboxes on the client, i.e. have the GSP only generate a short JavaScript method call with the variable parameters instead of the much larger (and more complex to parse for sitemesh) <select>

Michael Borgwardt
+5  A: 
  1. Update to the latest grails (1.2) should help.
  2. Upgrade to the latest JVM and consider JVM GC Optimizations (http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html)
  3. Configure Hibernate second level cache for Grails (see http://www.grails.org/GORM+-+Mapping+DSL for details)
  4. Install Java Melody plugin for grails (http://www.grails.org/plugin/grails-melody) - it will collect various statistics for you project and you will see what you should optimize.
  5. Install UI Performance plugin (http://www.grails.org/plugin/grails-melody) and analyze bottlenecks.
  6. Also consider installing PageSpeed (http://www.grails.org/plugin/grails-melody) or YSlow (https://addons.mozilla.org/en-US/firefox/addon/5369) to analyze client-side optimizations.
uthark
+1 for Grails-Melody - it gives you a wealth of information without having to do almost anything.
Jean Barmash
A: 

I would say, use Grails without GSP and only pure scriptlet JSP.

It would be the best trade-of between the productivity of Grails without the impossibly slow GSP.

My last project was a JSP one and I was forced to remove all slow tags to the native fast scriptlet, I would not even consider using any GSP in any project.

Try to write these 2 lines in a scriptlet.

"there no use trying to improve a bad algorithm, first, change the algorithm"

Geoffroy
Even though GSP is slower than JSP, I doubt very much that you will get the performance gains you will need to satisfy a business requirement of 5 or 10 or more times faster. In my experience these are the kinds of performance scaling which are typically expected. Sacrificing productivity for the negligible gains to be had from using pure JSP is - in my opinion - a very false economy when you should be considering the use of caches and CDNs as your first area of concern when attempting to scale beyond just 20% more.
j pimmel
A: 

Another great and free monitoring tool is Lambda Probe

http://www.lambdaprobe.org/

It's just a war you install in Tomcat, and gives you great informations about system and application (jvm, memory, etc.)

Wanderson Santos
Latest release: 28 Nov 2006..Seems pretty dead no?
fabien7474
@fabien7474 original project is quite dead, but it has fork on GoogleCode - http://code.google.com/p/psi-probe
Olexandr
A pretty dead that works great! Check it out first!
Wanderson Santos
A: 

I know that the original question included the words "the total amount of data is quite small", but if the amount of data had grown or is growing then some plain old database tuning may be required.

It's very easy to forget about adding database indexes because grails is so friendly at creating the datastore. Any tips on spotting long-running queries? Outputting all SQL can be fairly verbose.

javamelody plugin for Grails creates DataSource proxy so it suits well for queries profiling. http://code.google.com/p/javamelody/wiki/Screenshots
Olexandr