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 aorg.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.Cacheableclass CouponDocumentService {
    def xhmlDocumentService    Cacheable('couponDocumentCache')
    class getDocument(serial) {
        xhmlDocumentService.createDocument(template: '/coupon', model: [serial: serial])
    }
}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.Cacheableclass 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 theContent-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.