{"id":13595,"date":"2019-01-03T18:52:00","date_gmt":"2019-01-03T17:52:00","guid":{"rendered":"http:\/\/touk.pl\/blog\/?guid=38268a144208f2c5ebb42d63668ee2d3"},"modified":"2022-07-29T13:14:07","modified_gmt":"2022-07-29T11:14:07","slug":"loops-performance-in-groovy","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2019\/01\/03\/loops-performance-in-groovy\/","title":{"rendered":"Loops performance in Groovy"},"content":{"rendered":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>In the <a href=\"https:\/\/adventofcode.com\/2018\">2018 Advent of Code<\/a> challenged I solved all the puzzles in <a href=\"http:\/\/groovy-lang.org\/\">Groovy<\/a>. It is pretty obvious, that choosing good data structure is the most important to obtain performant solution. However, the way we iterate over those structures is also very significant, at least when using Groovy.<\/p>\n<h2 id=\"measuring-performance\">Measuring performance<\/h2>\n<p>I want to measure how long it takes to sum some numbers. For testing performance of loops I prepared a small function that simply sums some numbers:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">void printAddingTime(String message, long to, Closure&lt;Long&gt; adder) {\r\n    LocalTime start = LocalTime.now()\r\n    long sum = adder(to)\r\n    println(\"$message: $sum calculated in ${Duration.between(start, LocalTime.now()).toMillis()} ms\")\r\n}<\/pre>\n<p>Pseudo code for summing functions is below:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">for i = 1 to n\r\n  for j = 1 to n\r\n    sum += i * j\r\n  end\r\nend<\/pre>\n<h2 id=\"loops-types\"><code>Loops types<\/code><\/h2>\n<p>Let&#8217;s implement the summing function in various ways.<\/p>\n<h3 id=\"collect-and-sum\"><code>collect<\/code> and <code>sum<\/code><\/h3>\n<p>First loop type is to use built-in (by Groovy) function <code>collect<\/code> and <code>sum<\/code> on collections (<code>Range<\/code> it this example):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">(1..n).collect { long i -&gt;\r\n  (1..n).collect { long j -&gt;\r\n    i * j\r\n  }.sum()\r\n}.sum()<\/pre>\n<h3 id=\"each\"><code>each<\/code><\/h3>\n<p>Next, let&#8217;s write the same function using <code>each<\/code> built-in function on collections (<code>Range<\/code> it this example) and then add results to accumulator variable:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">long sum = 0\r\n(1..n).each { long i -&gt;\r\n    (1..n).each { long j -&gt;\r\n        sum += i * j\r\n    }\r\n}\r\nreturn sum<\/pre>\n<h3 id=\"times\"><code>times<\/code><\/h3>\n<p>Now instead of using <code>each<\/code> we could use the function <code>times<\/code> built-in on <code>Number<\/code> by Groovy:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">long sum = 0\r\nn.times { long i -&gt;\r\n  n.times { long j -&gt;\r\n    sum += (i + 1)*(j+1)\r\n  }\r\n}\r\nreturn sum<\/pre>\n<p>We have to add <code>1<\/code> to <code>i<\/code> and <code>j<\/code> because times generates numbers from <code>0<\/code> to <code>n<\/code> exclusive.<\/p>\n<h3 id=\"longstream-with-sum\"><code>LongStream<\/code> with <code>sum<\/code><\/h3>\n<p>Java 8 came with a new feature &#8211; streams. One example of streams is <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/util\/stream\/LongStream.html\"><code>LongStream<\/code><\/a>. Fortunately, it has <code>sum<\/code> built-in function, which we can use:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">LongStream.range(0, n).map { i -&gt;\r\n    LongStream.range(0, n).map { j -&gt;\r\n        (i + 1) * (j + 1)\r\n    }.sum()\r\n}.sum()<\/pre>\n<p><code>LongStream<\/code> generates numbers in the same way as <code>times<\/code> function, so we also have to add <code>1<\/code> to <code>i<\/code> and <code>j<\/code> here.<\/p>\n<h3 id=\"longstream-with-manual-sum\"><code>LongStream<\/code> with manual sum<\/h3>\n<p>Instead of <code>sum<\/code> function on <code>LongStream<\/code>, we can add all numbers manually:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">long sum = 0\r\nLongStream.range(0, n).forEach { i -&gt;\r\n    LongStream.range(0, n).forEach { j -&gt;\r\n        sum += (i + 1) * (j + 1)\r\n    }\r\n}\r\nreturn sum<\/pre>\n<h3 id=\"while\"><code>while<\/code><\/h3>\n<p>Of course since Groovy inherits from Java a big part of its syntax, we can use the <code>while<\/code> loop:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">long sum = 0\r\nlong i = 1\r\nwhile(i &lt;= n){\r\n    long j = 1\r\n    while(j &lt;= n){\r\n        sum+= i*j\r\n        ++j\r\n    }\r\n    ++i\r\n}\r\nreturn sum<\/pre>\n<h3 id=\"for\"><code>for<\/code><\/h3>\n<p>As we can use <code>while<\/code>, we can also use <code>for<\/code> loop in Groovy:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">long sum = 0\r\nfor (long i = 1; i &lt;= n; ++i) {\r\n    for (long j = 1; j &lt;= n; ++j) {\r\n        sum += i * j\r\n    }\r\n}\r\nreturn sum<\/pre>\n<p>&nbsp;<\/p>\n<h2 id=\"results\">Results<\/h2>\n<p>My tests I run on Java <code>1.8<\/code> and Groovy <code>2.5.5<\/code>. Script <code>loops.groovy<\/code> was fired using bash script:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">#!\/bin\/sh\r\nfor x in 10 100 1000 10000 100000; do\r\n  echo $x\r\n  groovy loops.groovy $x\r\n  echo\r\ndone<\/pre>\n<p>Values are in milliseconds<\/p>\n<table style=\"border-collapse: collapse\">\n<thead>\n<tr class=\"header\">\n<th style=\"border: 1px solid black\" align=\"left\">Loop \u00a0n<\/th>\n<th style=\"border: 1px solid black\" align=\"right\">10<\/th>\n<th style=\"border: 1px solid black\" align=\"right\">100<\/th>\n<th style=\"border: 1px solid black\" align=\"right\">1000<\/th>\n<th style=\"border: 1px solid black\" align=\"right\">10000<\/th>\n<th style=\"border: 1px solid black\" align=\"right\">100000<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>collect<\/code> + <code>sum<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">7<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">22<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">216<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">16244<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">1546822<\/td>\n<\/tr>\n<tr class=\"even\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>each<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">12<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">17<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">118<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">7332<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">706781<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>times<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">2<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">10<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">109<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">8264<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">708684<\/td>\n<\/tr>\n<tr class=\"even\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>LongStream<\/code> + <code>sum<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">7<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">17<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">127<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">7679<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">763341<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>LongStream<\/code> + manual sum<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">18<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">35<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">149<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">6857<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">680804<\/td>\n<\/tr>\n<tr class=\"even\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>while<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">8<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">20<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">103<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">3166<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">301967<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td style=\"border: 1px solid black\" align=\"left\"><code>for<\/code><\/td>\n<td style=\"border: 1px solid black\" align=\"right\">7<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">10<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">25<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">359<\/td>\n<td style=\"border: 1px solid black\" align=\"right\">27966<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As you can spot, for small amount of iterations using built-in Groovy functions is good enough, but for much bigger amount of iterations we should use <code>while<\/code> or <code>for<\/code> loops like in plain, old Java.<\/p>\n<h2 id=\"show-me-the-code\">Show me the code<\/h2>\n<p>Code for those examples are available <a href=\"https:\/\/gist.github.com\/alien11689\/3d92915142d70856f1fae2bd8351b7ea\">here<\/a>. You can run those examples on your machine and check performance on your own.<\/p>\n","protected":false},"excerpt":{"rendered":"IntroductionIn the 2018 Advent of Code challenged I solved all the puzzles in Groovy. It is pretty obvious, that choosing good data structure is the most important to obtain performant solution. However, the way we iterate over those structures is also&#8230;\n","protected":false},"author":54,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[651,50,652],"class_list":{"0":"post-13595","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-adventofcode","8":"tag-groovy","9":"tag-performance"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13595","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\/54"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=13595"}],"version-history":[{"count":7,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13595\/revisions"}],"predecessor-version":[{"id":14722,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13595\/revisions\/14722"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=13595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=13595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=13595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}