Improving Your Grails Application Performance (Look Jim No Stored Procedures) Well Greetings, it‟s always great to have application running on high CPU & more memory and that way you can always hide your code and environment mistakes. I did the same when I had a large instance of EC2 and IOPS enabled on the RDS, I designed and developed code which was less performance effective. But one day I moved my code to a medium EC2 with RDS having no IOPS, it all ran slow and more slow. My environment was Grails 2.1.1 & I had many plugins and huge DB with transactions which was like trying to insert 100k records frequently. The steps I followed Read all the blogs & I landed on Mr. Burt‟s presentation http://www.infoq.com/presentations/GORM-Performance (Great presentation) I picked one immediate helper from Burt (which someone stopped during the presentation and asked about) Grails>grails console The console helped me a lot for faster development, I could skip all the hoops of navigating through screens to get my code executed, no authentication, no steps just run . I pasted all my code in the console, Ctrl + R and it ran!! I changed my domain module to include only a reference of the parent‟s key instead of the whole object Example: Older Version public domain CustomerWeeklyServiceMenu { String id Date dateCreated Date lastUpdated Neev Information Technologies Pvt. Ltd.
www.neevtech.com
sales@neevtech.com
BigDecimal pricePerServing BigDecimal servingsQuantity CustomerWeeklyServiceMenu customerWeeklyServiceMenu Menu menu static transients = ['excluded'] ….. } New Version public domain CustomerWeeklyServiceMenu { String id Date dateCreated Date lastUpdated BigDecimal pricePerServing BigDecimal servingsQuantity CustomerWeeklyServiceMenuId MenuId static transients = ['excluded'] ….. } As you can see now I don‟t have the Parent Objects in the domain rather, I now have the ids of those domain classes (or tables) This is a good step to start with as Burt clearly mentions how Hibernate works with Collections and what can be the draw back if you don‟t do it this way.
Neev Information Technologies Pvt. Ltd.
www.neevtech.com
sales@neevtech.com
Second level Caching hibernate { cache.use_second_level_cache = true cache.use_query_cache = true cache.provider_class = „org.hibernate.cache.EhCacheProvider‟ } This will enable Hibernate‟s second level of caching for us. You need to add this in your DataSource.groovy You would need to perform changes in your domain class which you want to make use of the second level caching. static mapping = { cache usage: „read-only‟ } From Mr. Burts‟s presentation: ● The 1st level cache is the Hibernate Session ● Can significantly reduce database load by keeping instances in memory ● Can be distributed between multiple servers to let one instance load from the database and share updated instances, avoiding extra database trips ● “cache true” creates a read-write cache, best for read-mostly objects since frequently-updated objects will result in excessive cache invalidation (and network traffic when distributed) ● “cache usage: „read-only‟” creates a read-only cache, best for lookup data (e.g. Countries, States, Zip Codes, Roles, etc.) that never change ● DomainClass.get() always uses the 2nd-level cache ● By default nothing else always uses the cache but can be overridden Then you need to configure your Ehchace.xml Neev Information Technologies Pvt. Ltd.
www.neevtech.com
sales@neevtech.com
INDEXES We created indexes on parent classes after using explain on Mysql tables. It did help us to certain extent. Batch Updates I did CleanGorm after performing batch inserts. if (index % Constants.SQL_BATCH_SIZE == 0) cleanUpGorm(index)
def cleanUpGorm(def index) { def session = sessionFactory.currentSession session.flush() session.clear() } But I still did not see that big performance Run, then after reading more blogs and more books on hibernate, a thought came across if the session cache was very large. But that was the reason. Next, I read that Grails has FlushMode as “AUTO”, so I referred to this page on hibernate http://docs.jboss.org/hibernate/orm/3.5/javadoc/org/hibernate/FlushMode.html What I understood was that Grails before querying makes a “session” FLUSH?. That is very very bad!!. imported the org.hibernate.FlushMode & I put this line session.setflushMode(FlushMode.COMMIT) ICE breaker…..that‟s it !!, it was now I had 450K records in an hour instead of 20K in 2 hours. (This blog was authored by Mr. Uttam H.Naidu, Technical Architect at Neev Technologies) Visit us at Neevtech.com to know more about our offerings.
Neev Information Technologies Pvt. Ltd.
www.neevtech.com
sales@neevtech.com