(Quick Reference)

6 Caching And Performance - Reference Documentation

Authors: Grails Plugin Collective

Version: 1.0.0

6 Caching And Performance

Caching

Rendering can be an expensive operation so you may need to implement caching (using the excellent plugin)

Document Caching

Rendering works internally by creating a org.w3c.dom.Document instance from the GSP page via the xhtmlDocumentService. If you plan to render the same GSP as different output formats, you may want to cache the document.

import grails.plugin.springcache.annotations.Cacheable

class CouponDocumentService { def xhmlDocumentService

Cacheable('couponDocumentCache') class getDocument(serial) { xhmlDocumentService.createDocument(template: '/coupon', model: [serial: serial]) } }

All of the render methods can take a document parameter instead of the usual template/model properties.

class CouponController {

def couponDocumentService

def gif = { def serial = params.id def document = couponDocumentService.getDocument(serial)

renderGif(filename: "${serial}.gif", document) } }

Byte Caching

You can take things further and actually cache the rendered bytes.

import grails.plugin.springcache.annotations.Cacheable

class CouponGifService {

def couponDocumentService def gifRenderingService

def getGif(serial) { def document = couponDocumentService.getDocument(serial) def byteArrayOutputStream = gifRenderingService.gif([:], document) byteArrayOutputStream.toByteArray() } }

class CouponController {

def couponGifService

def gif = { def serial = params.id def bytes = couponGifService.getGif(serial)

renderGif(bytes: bytes, filename: "${serial}.gif") } }

Avoiding Byte Copying

When rendering to the response, the content is first written to a temp buffer before being written to the response. This is so the number of bytes can be determined and the Content-Length header set (this also applies when passing the bytes directly).

This copy can be avoided and the render (or bytes) can be written directly to the response output stream. This means that the Content-Length header will not be set unless you manually specify the length via the contentLength property to the render method.