Performance tuning your Grails apps

whoami > Colin Harrington

If a tree falls in a forest ...

does it make a sound?

and no one is around to hear it,

Metaphysics & Quantum Mechanics

  • George Berkeley asked the question
  • Albert Einstein & Neils Bohr
    • Bohr: "The moon does not exist if nobody is looking at it."
    • How do you prove it?  Prove me wrong

If your user hits a perf issue ...

does it matter to you?

and nobody reports it,




Measure first philosophy


  • Ask questions later
  • Data > no data


This app is slow.

    Perception burn!

May or may not report the issue (probably not)


User X loaded the results page in 1870ms today at 4:30pm

475 records were pulled from the DB

if (user.cares()) {
   if(user.canLocateSupport() && user.hasTime()) {

Perceived Performance

How your users feel is the reality that you are working with


Design & Code for your user


How One Second Could Cost Amazon $1.6 Billion In Sales


Front End



Client Heavy

Webapp Performance basics:

  • Originating HTTP request
  • Web Page (HTML)
  • Assets, js, css, images, etc.
  • Javscript app loading times
  • XHR (ajax) requests
  • SSE, websockets etc.

Bundling & Minification

Asset Pipeline Plugin

  • Asset Bundling
  • Extensible Modules (Supports LESS,Handlebars,Coffeescript, Ember-Handlebars, SASS) via other modules.
  • Cache Digest Names (Creates cache digested names and stores aliases in a
  • Js Minification
  • Js SourceMap Generation
  • Css Minification / Relative Path assertion
  • File Encoding Support
  • GZIP File Generation
  • Last-Modified Header

Separate Client & Server

Gradle Multi-module build

  • Standalone Client
    • javascript project
    • grunt, gulp, npm tooling, dependencies, bundling etc.
  • Server Backend
    • APIs
    • Rich data sources
    • Security measures
    • Testable & flexible

Content Delivery Network

  • Distributed & Built to be 'close' to clients
  • Caching mechanisms
  • Static assets
  • Maybe root html documents?
  • layered / uptime / DDOS protection

Preloading Data?

  • HTTP request
  • HTML Response
  • Browser
    • Parse HTML Document
    • Load referenced resources
    • Paint the page
    • Load Javascript app
    • Load Js dependencies
    • Initialize the app
    • API calls to fetch data. 

Front-end analytics 

  • Analytics platforms
  • Google Analytics
  • Pingdom
  • New Relic
  • many, many others

Error handling

  • Javascript testing!
    • Unit testing style
    • Browser testing
  • Error tolerant UX 
  • Visually Responsive vs blocking

Log client side Javascript errors!

  • Use a lib for your framework?
  • Roll your own?
  • Use a 3rd party
    • Track.js
    • Rollbar
    • Raygun
  • Web analytics platforms

Latency : Time scale


  • Code Performance
  • Reading from Drive
    • SSD
    • Rotational
  • Network latency
    • Same rack
    • Same building
    • Across the internet


Logs or it didn't happen

Quantify results

Human memory is 'lossy'

Removal of opinion

What happened surrounding


Grails uses logback

  •  grails-app/conf/logback.groovy
  •  grails-app/conf/logback.xml


(can also be configured externally)


Heisenberg effect

  • Observing influences performance
  •"Something happened") 
  •"Something happened ${expensiveEvaluation()}")

Async Appenders

  • Appenders blocking by default
  • AsyncAppender delegates
    • Any appender can be wrapped 
  • Durability vs performance
  • Appenders
    • File
    • DB
    • SMTP
    • Syslog
    • ...

Log Aggregation

Log Aggregation

  • Centralized
  • Debugging purposes
  • Analyzing
  • Usage/trends
  • spot & diagnose errors quickly
  • Handle Many types of logs
    • System Logs
    • Application Logs
    • Load balancer logs
    • Network device logs
    • front-end error logs


One place to rule them all!



Visual representation


Proxy/Load Balancer timing Logs are a great place to start


monitor traffic, analyze outliars


1 picture == 1000 words

Add context to log statements

  • Which Server
  • Which thread
  • CorrelationIDs
  • User/client identifier




Mapped Diagnostic Context (MDC)

  • User/client identifier
  • Early in the chain: Filter or Interceptor:
  • MDC.put("user",
  • Easy to search and filter

  • CorrelationID from the entry point

    • (also works if included in reactive flows)

Starting Point

  • Access Logs
    • Load balancer
    • Nginx
    • Tomcat access valve

Access logs

  • Request timing (duration, when)
  • HTTP status
  • Size of the response
  • Remote IP address
  • Thread that processed the request 
  • Session ID (tomcat)
  • Custom headers 

Look at min/max/average response times

Historical Performance

Did the performance change over time? 

Growing? at what rate?


  • Can be used as a simple Performance monitoring tool
class MyInterceptor {


  boolean before() { true }

  boolean after() { true }

  void afterView() {
    // no-op



  • Before the controller action
  • after the controller action
  • after the view layer is done
class MyInterceptor {


  boolean before() { true }

  boolean after() { true }

  void afterView() {
    // no-op


Profiling Tools

  • New Relic
  • Datadog
  • Solar Winds
  • YourKit Java Profiler (works great!)
  • JProfiler

YourKit Java Profiler 




  • Connection Pooling usage and settings
  • SQL Logging
  • Shim (wraps the client driver)
  • Enable Hibernate SQL logging
  • Query Logging on the actual server


* warning this can be chatty!

Enable SQL logging

logger("org.hibernate.SQL", DEBUG, ["STDOUT"], false)
logger("org.hibernate.type.descriptor.sql.BasicBinder", TRACE, ["STDOUT"], false)
        logSql: true
        formatSql: true

Application configuration


Profiling in other data sources

  • Mongo Profiling Level 
  • Redis monitoring or Slow log
  • MySQL Slow Log
  • Postgres logging slow queries

Slow Query

One expensive query

Usually a Complex query



1 * (Query Time + network overhead)

Many Queries

Many smaller less expensive queries

Overhead becomes important



n * (Query Time + network overhead)

GORM & Hibernate

ORMs are tough

Hibernate Session




Hibernate Second Level Cache

  • premature optimization?
  • Optimize frequently used objects

Hibernate Query Cache


(@See Burt's talk!)

Author Example

class Author {

    String name

    static hasMany = [books: Book]


new Book(title:"The Stand")
        .subscribe { Book it ->
    println "Title = ${it.title}"
    .subscribe { Book it ->
    println "Title = ${it.title}"


out of

procedural Jail




import static grails.async.Promises.*

def p1 = task { 2 * 2 }
def p2 = task { 4 * 4 }
def p3 = task { 8 * 8 }
assert [4,16,64] == waitAll(p1, p2, p3)
import static java.util.concurrent.TimeUnit.*
import static grails.async.Promises.*

Promise p = task {
        // Long running task
p.onError { Throwable err ->
        println "An error occured ${err.message}"
p.onComplete { result ->
    println "Promise returned $result"
// block until result is called
def result = p.get()
// block for the specified time
def result = p.get(1,MINUTES)
class BookService {
    List<Book> findBooks(String title) {
      // implementation
import grails.async.*

class AsyncBookService {
   @DelegateAsync BookService bookService

3rd Party API calls

  • Network overhead 100ms?
  • Orders of magnitude slower than code
  • Beware of mixing with Long running Transactions

JVM Performance

Garbage Collection

  • What type of GC?
  • GC logs
  • JVM monitoring tools

Visual VM

View layer

Grails Views

  • Statically Compiled Json Views!


Load Testing

  • Jmeter (older but flexible)
  • Gatling
  • etc.


Connect with Us

Thank you for attending!

Please visit our table for giveaways
and to meet the team!

Performance tuning your Grails apps

By Colin Harrington

Performance tuning your Grails apps

Gr8conf US 2017: You built it, they came - success!! What happens months or years later if your app grows and starts to slow down, grow too large or starts to be unreliable? We'll take a look at common pitfalls and their solutions, as well as take a more in-depth approach on how to address performance concerns. Whether Grails 2 or Grails 3, we'll dive into some real-world stories and cover some of the tricks and tools.

  • 1,616
Loading comments...

More from Colin Harrington