{"id":11690,"date":"2012-11-28T21:08:00","date_gmt":"2012-11-28T20:08:00","guid":{"rendered":"https:\/\/touk.pl\/blog\/?guid=b9772cdc8b184189a364db97686a7c76"},"modified":"2022-08-03T10:06:14","modified_gmt":"2022-08-03T08:06:14","slug":"use-xmls-not-groovy-scripts-with-db-migration-plugin-2","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2012\/11\/28\/use-xmls-not-groovy-scripts-with-db-migration-plugin-2\/","title":{"rendered":"Use XMLs not groovy scripts with db migration plugin!"},"content":{"rendered":"<p>I have 48 domain classes in my Grails 2.1 project and I use Grails Database Migration Plugin 1.2 for a database management. Recently I&#8217;ve noticed that it becomes terribly slow when running application, even if there are no changes to be applied.<\/p>\n<p>I switched do debug logging level for <code>liquibase<\/code> package and I found that it takes <strong>about 15 seconds<\/strong> to parse <code>changelog.groovy<\/code> and 20 files that were included in it!<\/p>\n<h3 id=\"prepare-benchmark\">Prepare benchmark<\/h3>\n<p>I couldn&#8217;t belive it so I&#8217;ve created two new clean changelogs:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">$ grails dbm-generate-changelog changelog.groovy\r\n$ grails dbm-generate-changelog changelog.xml<\/pre>\n<p>Both of these changelogs contain 229 change sets. It is enough that you can benchmark parsers for them. Two parsers in question are:<\/p>\n<ul>\n<li>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">grails.plugin.databasemigration.GrailsChangeLogParser<\/pre>\n<\/li>\n<li>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">liquibase.parser.core.xml.XMLChangeLogSAXParser<\/pre>\n<\/li>\n<\/ul>\n<p>I need to modify a line in my Config.groovy and switch <code>changelog.groovy<\/code> with <code>changelog.xml<\/code> for a second test:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">grails.plugin.databasemigration.updateOnStart = true\r\ngrails.plugin.databasemigration.updateOnStartFileNames = [\"changelog.groovy\"]\r\n\/\/ grails.plugin.databasemigration.updateOnStartFileNames = [\"changelog.xml\"] grails.plugin.databasemigration.updateOnStart = true\r\ngrails.plugin.databasemigration.updateOnStartFileNames = [\"changelog-all.groovy\"]\r\n\/\/ grails.plugin.databasemigration.updateOnStartFileNames = [\"changelog-all.xml\"]<\/pre>\n<h3 id=\"profile-with-jprofiler\">Profile with JProfiler<\/h3>\n<p>I want to profile execution time. I use <a href=\"http:\/\/www.ej-technologies.com\/products\/jprofiler\/overview.html\">JProfiler<\/a> from ej-technologies to measure execution times. Please notice that I don&#8217;t want to benchmark SQL queries performed by liquibase. I am only focused on <code>parse<\/code> method of these two classes.<\/p>\n<p>Here&#8217;s how I set up JProfiler:<\/p>\n<div class=\"separator\" style=\"clear: both;text-align: center\"><a style=\"margin-left: 1em;margin-right: 1em\" href=\"http:\/\/2.bp.blogspot.com\/-44EBamCJ6RA\/ULYbi7dG5GI\/AAAAAAAAAdc\/cmdcyV3drp8\/s1600\/liquibase1.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/2.bp.blogspot.com\/-44EBamCJ6RA\/ULYbi7dG5GI\/AAAAAAAAAdc\/cmdcyV3drp8\/s320\/liquibase1.jpg\" width=\"320\" height=\"302\" border=\"0\" \/><\/a> <a style=\"margin-left: 1em;margin-right: 1em\" href=\"http:\/\/2.bp.blogspot.com\/-EWYhL_tmu8A\/ULYbjTPcy1I\/AAAAAAAAAdo\/KlcqsVE-UEY\/s1600\/liquibase2.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/2.bp.blogspot.com\/-EWYhL_tmu8A\/ULYbjTPcy1I\/AAAAAAAAAdo\/KlcqsVE-UEY\/s320\/liquibase2.jpg\" width=\"320\" height=\"302\" border=\"0\" \/><\/a><\/div>\n<p>I switch to CPU Views &#8211; Method statistics and I click &#8220;Record&#8221;. Here are results for both parsers:<\/p>\n<h3 id=\"results-for-changelog-groovy\">Results for changelog.groovy<\/h3>\n<div class=\"separator\" style=\"clear: both;text-align: center\"><a style=\"margin-left: 1em;margin-right: 1em\" href=\"http:\/\/4.bp.blogspot.com\/-JqfMq3nJDaw\/ULYdtIp73NI\/AAAAAAAAAeA\/lL47TRyQDwI\/s1600\/liquibase4.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/4.bp.blogspot.com\/-JqfMq3nJDaw\/ULYdtIp73NI\/AAAAAAAAAeA\/lL47TRyQDwI\/s400\/liquibase4.jpg\" width=\"400\" height=\"230\" border=\"0\" \/><\/a><\/div>\n<h3 id=\"results-for-changelog-xml\">Results for changelog.xml<\/h3>\n<div class=\"separator\" style=\"clear: both;text-align: center\"><a style=\"margin-left: 1em;margin-right: 1em\" href=\"http:\/\/2.bp.blogspot.com\/-oB4m_jwSYac\/ULYdt8UemMI\/AAAAAAAAAeM\/yFYHlzJ1H_A\/s1600\/liquibase5.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/2.bp.blogspot.com\/-oB4m_jwSYac\/ULYdt8UemMI\/AAAAAAAAAeM\/yFYHlzJ1H_A\/s400\/liquibase5.jpg\" width=\"400\" height=\"230\" border=\"0\" \/><\/a><\/div>\n<h3 id=\"analysis\">Analysis<\/h3>\n<p>My assumptions were correct: 8 339 ms vs 139 ms. <strong>Parsing XML is 60 times faster!<\/strong> I want to jump and sing: &#8220;I switch to XML now!&#8221;, but I have some concerns. I have a production database that I need to be compatible with. And I should rewrite my all groovy changelog files by hand. So it&#8217;s not so trivial and it&#8217;s a time consuming and error prone task.<\/p>\n<p>So as much as I want to switch to XML now, I won&#8217;t. But if you start your adventure with database migration plugin today I have an advice for you: <strong>use XML if you start from scratch<\/strong>.<\/p>\n<p>For now I&#8217;ve just submitted a new JIRA issue &#8211; <a href=\"http:\/\/jira.grails.org\/browse\/GPDATABASEMIGRATION-107\">GrailsChangeLogParser &#8211; parse method is very slow<\/a> and I hope it can be greatly improved.<\/p>\n","protected":false},"excerpt":{"rendered":"I have 48 domain classes in my Grails 2.1 project and I use Grails Database Migration Plugin 1.2 for a database management. Recently I&#8217;ve noticed that it becomes terribly slow when running application, even if there are no changes to be applied. I swit&#8230;\n","protected":false},"author":37,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[687,50,68,407,409],"class_list":{"0":"post-11690","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-db","8":"tag-groovy","9":"tag-java","10":"tag-migration","11":"tag-profiling"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11690","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/37"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=11690"}],"version-history":[{"count":4,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11690\/revisions"}],"predecessor-version":[{"id":14917,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11690\/revisions\/14917"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=11690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=11690"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=11690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}