tag:blogger.com,1999:blog-84933864680303652592024-03-04T22:57:37.330-08:00Masato Nagai's BlogMasato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.comBlogger40125tag:blogger.com,1999:blog-8493386468030365259.post-62517126434669642512015-06-27T02:34:00.000-07:002015-06-27T06:37:20.633-07:00GProf supports Groovy 2.4<p><a href="http://gprof.gperfutils.org">GProf</a>, the Groovy Profiler supports <a href="http://www.groovy-lang.org/">Groovy</a> 2.4 in the new release version 0.3.1.</p>
<p>The release already has been available on the Maven Central repository and it means that now you can install GProf by the following one line:
<pre class="code">
@Grab('org.gperfutils:gprof:0.3.1-groovy-2.4') // v0.3.1 for Groovy 2.4
</pre>
</p>
<p>
Here is a demo:
<pre class="code">
// slow !!
def fib(n) {
if (n < 2) {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
profile {
fib(20)
}.prettyPrint()
</pre>
and the output will be like this:
<pre class="code">
Flat:
% cumulative self self total self total self total
time seconds seconds calls ms/call ms/call min ms min ms max ms max ms name
46.8 0.82 0.82 2 411.11 875.84 366.64 786.45 455.58 965.22 Prof.fib
35.1 1.43 0.61 21890 0.02 0.02 0.00 0.00 3.76 3.76 java.lang.Integer.minus
17.9 1.75 0.31 10945 0.02 0.02 0.00 0.00 1.79 1.79 java.lang.Integer.plus
0.0 1.75 0.00 1 0.74 1753.00 0.74 1753.00 0.74 1753.00 Prof$_run_closure1.fib
0.0 1.75 0.00 1 0.14 1753.15 0.14 1753.15 0.14 1753.15 Prof$_run_closure1.doCall
Call graph:
index % time self children calls name
0.00 1.75 1/1 <spontaneous>
[1] 100.0 0.00 1.75 1 Prof$_run_closure1.doCall [1]
0.00 1.75 1/1 Prof$_run_closure1.fib [2]
-----------------------------------------------------------------------------
0.00 1.75 1/1 Prof$_run_closure1.doCall [1]
[2] 99.9 0.00 1.75 1 Prof$_run_closure1.fib [2]
0.82 0.92 2/2 Prof.fib [3]
0.00 0.00 2/21890 java.lang.Integer.minus [4]
0.00 0.00 1/10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
0.82 0.92 2/2 Prof$_run_closure1.fib [2]
[3] 99.9 0.82 0.92 2+21888 Prof.fib [3]
0.61 0.00 21888/21890 java.lang.Integer.minus [4]
0.31 0.00 10944/10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
0.00 0.00 2/21890 Prof$_run_closure1.fib [2]
0.61 0.00 21888/21890 Prof.fib [3]
[4] 35.1 0.61 0.00 21890 java.lang.Integer.minus [4]
-----------------------------------------------------------------------------
0.00 0.00 1/10945 Prof$_run_closure1.fib [2]
0.31 0.00 10944/10945 Prof.fib [3]
[5] 17.9 0.31 0.00 10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
</pre>
</p>
<p>Last of all,</p>
<p>I'm sorry for the late release and <b>thanks for <a href="https://github.com/gperfutils/gprof/issues/7">kicking my butt</a></b>!</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAOHodgBII-QR_8BQArCMOrlP99dE4SXUh-ZUJpTFz_FU0DresK39vptRTqICqS5PKnduQZQE5GJXoOs-dYitvp_dnrpgVNvk3tBEV5hb5XEe8-i2OxzmxuEkdHLITmd_exYYt8Afta-jO/s1600/gperfutils_logo_medium.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAOHodgBII-QR_8BQArCMOrlP99dE4SXUh-ZUJpTFz_FU0DresK39vptRTqICqS5PKnduQZQE5GJXoOs-dYitvp_dnrpgVNvk3tBEV5hb5XEe8-i2OxzmxuEkdHLITmd_exYYt8Afta-jO/s320/gperfutils_logo_medium.gif" /></a>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com1tag:blogger.com,1999:blog-8493386468030365259.post-7021022970957055842015-02-14T01:24:00.001-08:002015-02-15T10:40:16.539-08:00GBench 0.4.3 released - Let's benchmark "as" operator in Groovy 2.4 and 2.3.<p>Today, I released version 0.4.3 of <a href="https://code.google.com/p/gbench/">GBench</a>, the benchmarking module for <a href="http://groovy.codehaus.org/">Groovy</a>.</p>
<p>The release is a maintenance release, but it includes a new feature, anonymous (unlabeled) code block syntax. The syntax makes your benchmarking code simpler when you have only one code block to be benchmarked. </p>
<pre class="code">
// benchmark {
// label {
// // code to be benchmarked
// }
// }
benchmark {
// code to be benchmarked
}
</pre>
<p>Let's benchmark using the syntax. This time's target is <a href="http://docs.codehaus.org/display/GROOVY/Groovy+2.4+release+notes#Groovy2.4releasenotes-Performanceimprovementsandreducedbytecode">"Optimization of primitive type conversions with the as operator (GROOVY-7140)"</a>. I wrote a the following benchmarking code:</p>
<pre class="code">
// Bench.groovy
import groovy.transform.CompileStatic
@CompileStatic
void test(char x) {
((((x as byte) as short) as int) as long)
}
benchmark {
test('a')
}.prettyPrint()
</pre>
<p>Here are the results of the code above with Groovy 2.3.0 and 2.4.0 in my environment.</p>
<pre class="code">
$ grape install org.gperfutils gbench 0.4.3-groovy-2.3
$ gvm use groovy 2.3.0
$ groovy -cp `find ~/.m2 -name gbench-0.4.3-groovy-2.3.jar` Bench.groovy
Environment
===========
* Groovy: 2.3.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (24.75-b04, Oracle Corporation)
* JRE: 1.7.0_75
* Total Memory: 491.5 MB
* Maximum Memory: 910.5 MB
* OS: Mac OS X (10.10.1, x86_64)
Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On
user system cpu real
1822 3 1825 1828
</pre>
<pre class="code">
$ grape install org.gperfutils gbench 0.4.3-groovy-2.4
$ gvm use groovy 2.4.0
$ groovy -cp `find ~/.m2 -name gbench-0.4.3-groovy-2.4.jar` Bench.groovy
Environment
===========
* Groovy: 2.4.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (24.75-b04, Oracle Corporation)
* JRE: 1.7.0_75
* Total Memory: 491.5 MB
* Maximum Memory: 910.5 MB
* OS: Mac OS X (10.10.1, x86_64)
Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On
user system cpu real
1543 3 1546 1549
</pre>
<p>It seems no doubt that the performance of "as" operator was improved in Groovy 2.4.0. So how did they make it? The difference between the following bytecode snippets is the answer.</p>
<p>Groovy 2.3.0</p>
<pre class="code">
public void test(char);
Code:
0: iload_1
1: invokestatic #74 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
4: getstatic #80 // Field java/lang/Byte.TYPE:Ljava/lang/Class;
7: invokestatic #84 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.asType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
10: invokestatic #90 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.byteUnbox:(Ljava/lang/Object;)B
13: invokestatic #93 // Method java/lang/Byte.valueOf:(B)Ljava/lang/Byte;
16: getstatic #96 // Field java/lang/Short.TYPE:Ljava/lang/Class;
19: invokestatic #84 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.asType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
22: invokestatic #100 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.shortUnbox:(Ljava/lang/Object;)S
25: invokestatic #103 // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
28: getstatic #106 // Field java/lang/Integer.TYPE:Ljava/lang/Class;
31: invokestatic #84 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.asType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
34: invokestatic #110 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.intUnbox:(Ljava/lang/Object;)I
37: invokestatic #113 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
40: getstatic #116 // Field java/lang/Long.TYPE:Ljava/lang/Class;
43: invokestatic #84 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.asType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
46: invokestatic #120 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.longUnbox:(Ljava/lang/Object;)J
49: pop2
50: return
</pre>
<p>Groovy 2.4.0</p>
<pre class="code">
public void test(char);
Code:
0: iload_1
1: i2b
2: i2s
3: i2l
4: pop2
5: return
</pre>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-69952279503088037582013-11-08T19:31:00.001-08:002013-11-08T22:23:31.309-08:00Build OpenJFX 8 on OS X 10.9 Mavericks1. Clone <a href="http://openjdk.java.net/projects/openjfx/">OpenJFX 8</a>.
<pre class="code">
$ openjfx% hg clone http://hg.openjdk.java.net/openjfx/8/graphics/rt
$ openjfx% cd rt
</pre>
2. Checkout a tag for your JDK.
<pre class="code">
$ openjfx/rt% java -version 2>&1 | grep "build 1.8"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b111)
$ openjfx/rt% hg checkout 8.0-b111
</pre>
3. Set properties for Mavericks.
<pre class="code">
$ openjfx/rt% cat gradle.properties
MACOSX_MIN_VERSION=10.9
MACOSX_JDK_FRAMEWORK=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework
</pre>
4. Build jfxrt.jar.
<pre class="code">
$ openjfx/rt% gradle jfxrtMac
</pre>
5. (If you want to use OpenJFX as default) Replace the bundled jar with the jar you built.
<pre class="code">
$ openjfx/rt% sudo mv $JAVA_HOME/jre/lib/ext/jfxrt.jar $JAVA_HOME/jre/lib/ext/jfxrt.jar.orig
$ openjfx/rt% sudo cp build/mac-sdk/rt/lib/ext/jfxrt.jar $JAVA_HOME/jre/lib/ext/jfxrt.jar
</pre>
That's it. Enjoy the open source JavaFX ;)Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-90258305547914397152013-09-14T06:52:00.000-07:002013-09-14T07:05:30.654-07:00GProf 0.3.0 is out!<p>Today I released the Groovy profiler, <a href="https://code.google.com/p/gprof/"><b>GProf 0.3.0</b></a>. GProf is a profiling module for Groovy which is developed in GPerfUtils project at http://gperfutils.org. The release includes the GNU profiler compatible call graph report and many improvements. You can read all the changes at <a href="https://code.google.com/p/gprof/wiki/ReleaseNotes030">https://code.google.com/p/gprof/wiki/ReleaseNotes030</a>).</p>
<p>The release already has been available on the Maven Central repository and it means that now you can install GProf by the following one line:
<pre class="code">
@Grab('org.gperfutils:gprof:0.3.0-groovy-2.1') // v0.3.0 for Groovy 2.1
</pre>
</p>
<p>
Here is a demo:
<pre class="code">
// slow !!
def fib(n) {
if (n < 2) {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
profile {
fib(20)
}.prettyPrint()
</pre>
and the output will be like this:
<pre class="code">
Flat:
% cumulative self self total self total self total
time seconds seconds calls ms/call ms/call min ms min ms max ms max ms name
54.3 0.29 0.29 2 145.86 267.78 38.14 58.56 253.57 477.00 demo.fib
30.4 0.45 0.16 21890 0.00 0.00 0.00 0.00 0.80 0.80 java.lang.Integer.minus
15.0 0.53 0.08 10945 0.00 0.00 0.00 0.00 0.83 0.83 java.lang.Integer.plus
0.1 0.53 0.00 1 1.05 537.10 1.05 537.10 1.05 537.10 demo$_run_closure1.fib
0.0 0.53 0.00 1 0.13 537.23 0.13 537.23 0.13 537.23 demo$_run_closure1.doCall
Call graph:
index % time self children calls name
0.00 0.53 1/1 <spontaneous>
[1] 100.0 0.00 0.53 1 demo$_run_closure1.doCall [1]
0.00 0.53 1/1 demo$_run_closure1.fib [2]
-----------------------------------------------------------------------------
0.00 0.53 1/1 demo$_run_closure1.doCall [1]
[2] 99.9 0.00 0.53 1 demo$_run_closure1.fib [2]
0.29 0.24 2/2 demo.fib [3]
0.00 0.00 2/21890 java.lang.Integer.minus [4]
0.00 0.00 1/10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
0.29 0.24 2/2 demo$_run_closure1.fib [2]
[3] 99.6 0.29 0.24 2+21888 demo.fib [3]
0.16 0.00 21888/21890 java.lang.Integer.minus [4]
0.08 0.00 10944/10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
0.00 0.00 2/21890 demo$_run_closure1.fib [2]
0.16 0.00 21888/21890 demo.fib [3]
[4] 30.4 0.16 0.00 21890 java.lang.Integer.minus [4]
-----------------------------------------------------------------------------
0.00 0.00 1/10945 demo$_run_closure1.fib [2]
0.08 0.00 10944/10945 demo.fib [3]
[5] 15.0 0.08 0.00 10945 java.lang.Integer.plus [5]
-----------------------------------------------------------------------------
</pre>
</p>
<p>
I welcome any requests or feedback.
</p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com1tag:blogger.com,1999:blog-8493386468030365259.post-71423351345405703272013-05-02T22:27:00.001-07:002013-05-03T02:48:03.335-07:00GBench Goodness: Compare the performance of different versions of Groovy using GVM<p>As I announced in my last post, <a href="http://blog.masatonagai.com/2013/04/gprof-goodness-profile-forkjoin-program.html"><i>"GProf Goodness: Profile a fork/join program written in GPars"</i></a>, I started Goodness series for GPerfUtils (<a href="http://gbench.gperfutils.org">GBench</a> and <a href="http://gprof.gperfutils.org">GProf</a>). And now it's the turn of GBench.</p>
<p>GBench is the benchmarking module of Groovy. It allow you to accurately and easily benchmark a Groovy program. <a href="http://gvmtool.net/">GVM</a> is a tool for managing parallel versions of Groovy and other Groovy-related tools. By combining the tools, you can easily compare the performance of different versions of Groovy. This is a script to compare the performance of <a href="http://en.wikipedia.org/wiki/Fibonacci_number">Fibonacci number</a> calculation among v1.7.11, v1.8.9, v2.0.8, and v2.1.3 (you have to install GVM first if you haven't done it yet).</p>
<p>
</p>
<pre class="code">
#!/bin/bash
source ~/.gvm/bin/gvm-init.sh
versions=(1.7.11 1.8.9 2.0.8 2.1.3)
for version in ${versions[*]}
do
echo -n "Install groovy v${version}"
gvm install groovy $version
done
echo "Okie-dokie, let's benchmark them!"
for version in ${versions[*]}
do
gvm use groovy $version > /dev/null &&
running_version=$(groovy -v | cut -d' ' -f 3) &&
major_version=$(echo $running_version | cut -d'.' -f1,2) &&
groovy -e "
@Grab('org.gperfutils:gbench:0.4.2-groovy-${major_version}')
def fib(int n) {
(n < 2) ? 1 : fib(n - 1) + fib(n - 2)
}
// benchmark() extension is supported only in Groovy 2.0 or later versions.
new groovyx.gbench.BenchmarkBuilder().run(quiet:true, measureCpuTime:false) {
'v${major_version}' { fib(20) }
}.prettyPrint()
" &&
sleep 1
done
</pre>
<div>
<p>[NOTE] If you face "gvm: command not found" error, try the following approach until <a href="https://github.com/gvmtool/gvm/pull/159">my pull request for fixing the issue</a> is merged to GVM. </p>
<ol>
<li> Download <a href="https://gist.github.com/masatonagai/5507103">gvm-include.sh</a> from my Gists</li>
<li> Make gvm-include.sh executable by "chmod +x gvm-include.sh"</li>
<li> Replace "source ~/.gvm/bin/gvm-include.sh" in the benchmark script to "source /path/to/gvm-include.sh"</li>
</ol>
</div>
<p>This is the results of the script in my environment. This shows us that the performance of numeric operations were highly improved in v1.8 at least:</p>
<pre class="code">
v1.7 870633
v1.8 535506
v2.0 507253
v2.1 489244
</pre>
<p>
Please send me pull requests at <a href="https://github.com/gperfutils/gbench">the Github page</a> or any issues, requests to <a href="https://code.google.com/p/gbench/issues/list">the Issue page</a> to improve GBench.
</p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-10545291278155731172013-04-26T19:16:00.000-07:002013-05-02T23:56:47.327-07:00GProf Goodness: Profile a fork/join program written in GPars<p>
I just started to write Goodness series for <a href="http://gperfutils.org">GPerfUtils</a> (<a href="http://gbench.gperfutils.org"><b>GBench</b></a> and <a href="http://gprof.gperfutils.org"><b>GProf</b></a>) like the great <a href="http://mrhaki.blogspot.jp/search/label/Groovy%3AGoodness">Groovy Goodness</a> series by Hubert Klein. And this is the first post of GProf Goodness.
</p>
<p>
First of all, I should explain about GProf. GProf is the profiling module for <a href="http://groovy.codehaus.org/">Groovy</a>. The purpose of the module is agile profiling. It means that you can profile Groovy program whenever and wherever you want. You don't have to go through lengthy tiresome procedure.
</p>
<p>
OK, let's back to the topic. GProf supports multi-threaded programs. The following example is to profile a fork/join example of <b><a href="http://gpars.codehaus.org/">GPars</a></b> from <a href="http://gpars.codehaus.org/ForkJoin">the GPars user guide</a>.
<pre class="code">
// prof.groovy
@Grab('org.gperfutils:gprof:0.2.0')
import static groovyx.gpars.GParsPool.runForkJoin
import static groovyx.gpars.GParsPool.withPool
profile {
withPool(2) { pool ->
println """Number of files: ${
runForkJoin(new File("./src")) {file ->
long count = 0
file.eachFile {
if (it.isDirectory()) {
forkOffChild(it) //fork a child task
} else {
count++
}
}
return count + (childrenResults.sum(0))
//use results of children tasks to calculate and store own result
}
}"""
}
}.prettyPrint()
</pre>
The results will be like this:
<pre class="code">
Number of files: 2145
% calls total ms ms/call min ms max ms method class
29.47 1 342.87 342.87 342.87 342.87 runForkJoin groovyx.gpars.forkjoin.ForkJoinUtils
14.87 2403 173.04 0.07 0.05 4.09 doCall prof$_run_closure1_closure2_closure3_closure4
9.41 2403 109.51 0.05 0.03 4.06 isDirectory java.io.File
9.16 259 106.61 0.41 0.11 9.08 eachFile java.io.File
8.83 259 102.72 0.40 0.10 21.59 doCall prof$_run_closure1_closure2_closure3
4.80 2145 55.81 0.03 0.02 2.80 next java.lang.Long
3.61 1 42.00 42.00 42.00 42.00 use groovyx.gpars.GParsPool
2.90 1 33.73 33.73 33.73 33.73 call prof$_run_closure1_closure2
2.53 1 29.39 29.39 29.39 29.39 withExistingPool groovyx.gpars.GParsPool
2.46 258 28.68 0.11 0.04 14.86 forkOffChild prof$_run_closure1_closure2_closure3
1.92 1 22.34 22.34 22.34 22.34 createPool groovyx.gpars.GParsPool
1.56 2 18.12 9.06 4.99 13.13 withPool groovyx.gpars.GParsPool
1.43 258 16.66 0.06 0.04 4.32 forkOffChild prof$_run_closure1_closure2_closure3_closure4
1.40 409 16.24 0.04 0.02 0.93 plus java.lang.Long
1.28 258 14.89 0.06 0.04 0.84 forkOffChild groovyx.gpars.forkjoin.FJWorker
0.94 1 10.93 10.93 10.93 10.93 println prof$_run_closure1_closure2
0.80 108 9.27 0.09 0.04 0.71 sum java.util.Arrays$ArrayList
0.75 1 8.67 8.67 8.67 8.67 runForkJoin groovyx.gpars.GParsPool
0.64 151 7.48 0.05 0.02 1.86 sum java.util.Collections$EmptyList
0.36 1 4.18 4.18 4.18 4.18 asType groovyx.gpars.GParsPool$_createDefaultUncaughtExceptionHandler_closure4
0.25 108 2.85 0.03 0.02 0.05 plus java.lang.Integer
0.20 1 2.28 2.28 2.28 2.28 getAt [Ljava.lang.String;
0.10 1 1.13 1.13 1.13 1.13 ctor jsr166y.ForkJoinPool
0.06 2 0.68 0.34 0.03 0.66 size [Ljava.lang.Object;
0.05 1 0.61 0.61 0.61 0.61 isCase groovy.lang.IntRange
0.05 1 0.61 0.61 0.61 0.61 minus java.lang.Integer
0.05 1 0.61 0.61 0.61 0.61 retrieveCurrentPool groovyx.gpars.GParsPool
0.04 1 0.44 0.44 0.44 0.44 toInteger java.lang.String
0.03 1 0.32 0.32 0.32 0.32 retrieveDefaultPoolSize groovyx.gpars.util.PoolUtils
0.02 2 0.21 0.10 0.07 0.14 doCall groovyx.gpars.GParsPool$_withExistingPool_closure1
0.01 1 0.11 0.11 0.11 0.11 leftShift groovyx.gpars.ThreadLocalPools
0.01 1 0.11 0.11 0.11 0.11 shutdown jsr166y.ForkJoinPool
0.01 1 0.09 0.09 0.09 0.09 awaitTermination jsr166y.ForkJoinPool
0.01 2 0.09 0.04 0.04 0.05 getAt [Ljava.lang.Object;
0.01 1 0.07 0.07 0.07 0.07 ctor groovyx.gpars.ThreadLocalPools
0.01 1 0.07 0.07 0.07 0.07 pop groovyx.gpars.ThreadLocalPools
0.00 1 0.05 0.05 0.05 0.05 ctor java.io.File
0.00 1 0.04 0.04 0.04 0.04 asType prof$_run_closure1_closure2_closure3
</pre>
</p>
Also, you can choose threads that you are interested in by includeThreads and excludesThreads options. The following change is to profile only worker threads which GPars gives a name starting with "ForkJoinPool". The options allow "*" and "?" wildcards. You don't have to specify the names of all the threads.
</p>
<pre class="code">
// profile {
profile(includeThreads: [ "ForkJoinPool*" ]) {
...
}.prettyPrint()
</pre>
The results will be changed like this:
<pre class="code">
Number of files: 2145
% calls total ms ms/call min ms max ms method class
27.42 2403 268.07 0.11 0.07 4.12 doCall prof$_run_closure1_closure2_closure3_closure4
21.63 2403 211.49 0.09 0.04 52.46 isDirectory java.io.File
14.20 2145 138.80 0.06 0.03 51.11 next java.lang.Long
13.61 259 133.05 0.51 0.12 13.41 eachFile java.io.File
9.40 259 91.94 0.35 0.14 12.16 doCall prof$_run_closure1_closure2_closure3
3.54 258 34.61 0.13 0.05 15.03 forkOffChild prof$_run_closure1_closure2_closure3
2.58 409 25.22 0.06 0.03 4.28 plus java.lang.Long
1.98 258 19.39 0.08 0.05 1.20 forkOffChild groovyx.gpars.forkjoin.FJWorker
1.95 258 19.06 0.07 0.05 0.52 forkOffChild prof$_run_closure1_closure2_closure3_closure4
1.66 108 16.18 0.15 0.06 3.94 sum java.util.Arrays$ArrayList
1.15 108 11.20 0.10 0.03 6.34 plus java.lang.Integer
0.90 151 8.81 0.06 0.03 1.97 sum java.util.Collections$EmptyList
</pre>
<p>
Please send me pull requests at <a href="https://github.com/gperfutils/gprof">the Github page</a> or any issues, requests to <a href="https://code.google.com/p/gprof/issues/list">the Issue page</a> to improve GProf.</p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com13tag:blogger.com,1999:blog-8493386468030365259.post-8127081327635164592013-04-20T03:30:00.001-07:002013-04-20T03:52:23.849-07:00This is the logo for GProf and GBench!!<pre>
I just drew the logo for <a href="http://gperfutils.org"><b>GPerfUtils</b></a> project that has <a href="http://gprof.gperfutils.org"><b>GProf</b></a> and <a href="http://gbench.gperfutils.org"><b>GBench</b></a>. I am not a good artist but I personally like the logo that is based on <a href="http://groovy.codehaus.org/download/attachments/40992780/image-duke.png?version=1&modificationDate=1198295557201">the Groovy Duke</a>. How about you?
</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-F1IboHW7kQ7k2YMxutmoQbDrKlU3zIwctLILCHxY6VsBVFCoPXUX_bvq8tnheKd2BUjunvVPKH8OBsgtv955GLRmq-n-KkNSfTTHKeHzgqZ_9tZO9tk-bctQDwnNyi95zoPWjvOMApqo/s1600/gperfutils_logo_medium.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-F1IboHW7kQ7k2YMxutmoQbDrKlU3zIwctLILCHxY6VsBVFCoPXUX_bvq8tnheKd2BUjunvVPKH8OBsgtv955GLRmq-n-KkNSfTTHKeHzgqZ_9tZO9tk-bctQDwnNyi95zoPWjvOMApqo/s320/gperfutils_logo_medium.gif" /></a>
<pre>
And this is the sketch.
</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZ2v6wTXosCI95KC2izla7R2_dxLwRgz1BrY1vNPNgekY8FH2XWYEuZYJNzciPC8qgWhlqNeASQSqLYvKv4L_kxs-n6yPZPDB-lAoaJzXDBBG6S5lUgzj0C1Ovl9pVEuhiaPvvkIxvU_2/s1600/gperfutils_logo_sketch_medium.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZ2v6wTXosCI95KC2izla7R2_dxLwRgz1BrY1vNPNgekY8FH2XWYEuZYJNzciPC8qgWhlqNeASQSqLYvKv4L_kxs-n6yPZPDB-lAoaJzXDBBG6S5lUgzj0C1Ovl9pVEuhiaPvvkIxvU_2/s320/gperfutils_logo_sketch_medium.gif" /></a>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-53179863389501167302013-04-14T07:04:00.001-07:002013-04-14T09:33:00.339-07:00GProf 0.2.0 is out!Today I released <b>GProf 0.2.0</b>! GProf is a profiling module for Groovy which is developed in <b>GPerfUtils</b> project at <a href="http://gperfutils.org">http://gperfutils.org</a>. <b>GBench</b> which is a benchmarking module for Groovy is also a subproject of GPerfUtils. The release already has been available on the Maven Central repository and it means that now you can install GProf by the following one line:
<pre class="code">
@Grab('org.gperfutils:gprof:0.2.0')
</pre>
The release includes big enhancements and important bug fixes. The changes are as follows (you can read it also at <a href="https://raw.github.com/gperfutils/gprof/master/NEWS">https://raw.github.com/gperfutils/gprof/master/NEWS</a>):
<pre class="code">
Support multi-threaded applications
Support Grape
Add includeMethods and excludeMethods options that filter by the name of packages,
classes and methods:
It supports the following wildcards:
| * | zero or more characters |
| ? | exactly one character |
The following example profile only methods which are of "java.*" or "groovy.*"
package but are not constructors:
profile(
includeMethods: [ "java.*", "groovy.*" ],
excludeMethods: [ "*.ctor" ]) {
// code to be profiled
}
Add includeThreads and excludeThreads options that filter by the name of threads:
It supports the following wildcards:
| * | zero or more characters |
| ? | exactly one character |
The following example profile only methods which are called in the "thread-*"
thread but not in "thread-2" or "thread-3":
profile(
includeThreads: [ "thread-*" ],
excludeThreads: [ "thread-2", "thread-3" ]) {
// code to be profiled
}
Bug fixes:
- #3: GProf fails to profile a multi-threaded application
- #4: Contains the time of children if the depth is more than two
- #6: There are classes that are not profiled
</pre>
Enjoy ;)Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-68205813161777379462013-04-03T08:27:00.003-07:002013-04-03T08:27:52.302-07:00GProf was just born!<p><b>GProf</b> a.k.a. <b>Groovy gprof</b> was just born Yesterday [<a href="https://code.google.com/p/gprof/">https://code.google.com/p/gprof/</a>]. GProf is a profiler for <b>Groovy</b> [<a href="http://groovy.codehaus.org/">http://groovy.codehaus.org/</a>]. It allows you to determine which parts of a program are taking most of the execution time like GNU gprof does for C, C++.</p>
<p>For example, in the following code, GProf shows you that YourApp has two slow operation; one is a task that is short but repeated many times and another is a long task.</p>
<pre class="code">
class YourApp {
void start() {
def foo = new Foo()
for (int i = 0; i < 100; i++) {
foo.doShortTask()
}
def bar = new Bar()
bar.doLongTask()
}
}
class Bar {
void doLongTask() {
for (int i = 0; i < 1000000; i++);
}
}
class Foo {
void doShortTask() {
for (int i = 0; i < 10000; i++);
}
}
profile { // or new gprof.Profiler().run {
new YourApp().start()
}.prettyPrint()
/* stdout
% calls total ms ms/call min ms max ms method class
47.59 1 54.33 54.33 54.33 54.33 doLongTask Bar
40.05 100 45.72 0.46 0.29 2.09 doShortTask Foo
11.92 1 13.61 13.61 13.61 13.61 start YourApp
0.18 1 0.21 0.21 0.21 0.21 ctor YourApp
0.13 1 0.14 0.14 0.14 0.14 ctor Bar
0.13 1 0.14 0.14 0.14 0.14 ctor Foo
*/
</pre>
Please try GProf and send me your feecback. Enjoy!
Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-83166908820470761222013-03-25T09:11:00.000-07:002013-03-25T10:00:53.585-07:00GBench 0.4.2 released!<p>Today I released <b>GBench 0.4.2</b>, the benchmarking module of <b>Groovy</b> <a href="http://groovy.codehaus.org/">http://groovy.codehaus.org/</a>. The release includes new system properties and fixes for providing more exact benchmark. Please check the release notes <a href="https://code.google.com/p/gbench/wiki/ReleaseNotes042">https://code.google.com/p/gbench/wiki/ReleaseNotes042</a> or visit the project site <a href="https://code.google.com/p/gbench/">https://code.google.com/p/gbench/</a> for more info. </p>
</p>And now I started developing GBench 0.5.0. If you have requests or anything for this module, please send me a message or add a new issue to <a href="https://code.google.com/p/gbench/issues/list">https://code.google.com/p/gbench/issues/list</a>. Enjoy!Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-11565098199030143682013-03-16T02:14:00.000-07:002013-03-16T02:51:36.882-07:00GBench tutorial is now available!<p>For open source projects, one of the most important is without any doubt documentation. For example, Groovy project declared that they will make efforts to improve their documents few days ago: <a href="http://groovy.329449.n5.nabble.com/ANN-Documentation-effort-and-site-redesign-td5712875.html">http://groovy.329449.n5.nabble.com/ANN-Documentation-effort-and-site-redesign-td5712875.html</a></p>
<p>Therefore, I also wrote a tutorial for GBench, the benchmarking module for Groovy: <a href="https://code.google.com/p/gbench/wiki/BenchmarkBuilderTutorial">https://code.google.com/p/gbench/wiki/BenchmarkBuilderTutorial</a></p> It is a bit short but I hope this document helps your Groovy life as much as possible :)Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-16183945121002672432013-03-08T05:17:00.002-08:002013-03-08T05:17:35.971-08:00GBench 0.4.1 released!Today I released GBench 0.4.1, the benchmarking module of <a href="http://groovy.codehaus.org/">Groovy</a>. The release includes an important bug fix for Invokedynamic. Please visit the GBench project site <a href="https://code.google.com/p/gbench/">https://code.google.com/p/gbench/</a> for more info.Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com1tag:blogger.com,1999:blog-8493386468030365259.post-35264732203030185602012-12-22T00:25:00.001-08:002013-05-03T03:50:54.391-07:00Multiple Dispatch in Modern JVM Languages<h3>What is dispatch?</h3><p>
"dispatch" in the context of object-oriented languages means that calling one of subroutines that have the same names by checking the parameters dynamically. There are multiple and single for dispatch. I'll write about dispatch and its support in Java and other modern JVM languages in this post.</p>
<h3>Java</h3><p>
Java is "single dispatch". I'll describe it with an example of handling touch events. Let me assume that there are classes that express touch events and they have parent class named TouchEvent, also, there is TouchEventHandler that handles touch events (the y might have a virtual upper layer in an actual API).</p>
<pre class="code">
class TouchEvent {}
class TouchStartEvent extends TouchEvent {}
class TouchMoveEvent extends TouchEvent {}
class TouchEndEvent extends TouchEvent {}
class TouchCancelEvent extends TouchEvent {}
class TouchEventHandler {
void handle(TouchEvent e) {}
}
</pre>
<p>Let me assume that you want to create a handler that changes behaviour depending on if the the parameter is TouchEvent or TouchStartEvent. I guess that you will write code like this if you expect subtype polymorphism.</p>
<pre class="code">class MyTouchEventHandler extends TouchEventHandler {
public void handle(TouchEvent e) {
System.out.println("... ?:(");
}
public void handle(TouchStartEvent e) {
System.out.println("touch started :)");
}
}
</pre>
<p>But the code doesn't work well.</p>
<pre class="code">TouchEventHandler h = new MyTouchEventHandler();
h.handle(new TouchStartEvent()); // prints "... ?:("
</pre>
<p>Java refers MyTouchEventHandler but it calls <i>handle(TouchEvent)</i> but not <i>handle(TouchStartEvent)</i>. In more technical terms, Java resolves the type of the receiver dynamically but resolves the other parameters statically when sending the message. This is called "single dispatch". I'll modify the code to enhance the gap between expect for the code and compiler's opinion.</p>
<pre class="code">class MyTouchEventHandler extends TouchEventHandler {
@Override public void handle(TouchEvent e) {
System.out.println("... :(");
}
@Override public void handle(TouchStartEvent e) {
System.out.println("It's my turn! :)");
}
}
</pre>
<p>Then compiler will say</p>
<pre class="code">src/Overloading.java:19: error: method does not override or implement a method from a supertype
@Override public void handle(TouchStartEvent e) {
^
</pre>
<p>There is a way to simulate "multiple dispatch" in Java code (without tricks in compilation phase) and I'll describe it in the following section about Xtend.</p>
<h3>Xtend</h3><p>
<a href="http://www.eclipse.org/xtend/">Xtend</a> is a relatively new JVM language that has appeared in the last year ("relatively" means that a new JVM language has appeared in this year too). Xtend is "single dispatch" as Java, but it also supports "multiple dispatch" by "dispatch" keyword.</p>
<pre class="code">class MyTouchEventHandler extends TouchEventHandler {
def dispatch void handle(TouchEvent e) {
println("... :(")
}
def dispatch void handle(TouchStartEvent e) {
println("touch started :)")
}
}
val TouchEventHandler h = new MyTouchEventHandler()
h.handle(new TouchStartEvent()) // prints "touch started :)"
</pre>
<p>It's easy to grasp what Xtend does because Xtend generates Java files instead of class files. Xtends puts a proxy method that delegates to methods have "dispatch" keyword. This is the way to simulate "multiple dispatch" in Java that I mentioned before.</p>
<pre class="code">
public class MyTouchEventHandler extends TouchEventHandler {
protected void _handle(final TouchEvent e) {
InputOutput.<String>println("... :(");
}
protected void _handle(final TouchStartEvent e) {
InputOutput.<String>println("touch started :)");
}
public void handle(final TouchEvent e) {
if (e instanceof TouchStartEvent) {
_handle((TouchStartEvent)e);
return;
} else if (e != null) {
_handle(e);
return;
} else {
throw new IllegalArgumentException("Unhandled parameter types: " +
Arrays.<Object>asList(e).toString());
}
}
}
</pre>
<p>I think that using one underscore for prefix isn't nice because programmers need to worry about naming collision but let's leave it aside for now. My interest is why Xtend is "single dispatch" by default. I asked the question to Sven Efftinge who is one of the authors of Xtend and he answered <i><b>"because changing method resolution would impose many interop issues with existing Jave libs"</i></b>. I guess it's unhappy that spoiling writability of new lauguage for taking care about bad old Java code depend on "single dispatch" but it might be because that I have never had an awful experience. Anyway, Xtend supports "multiple dispatch".</p>
<h3>Groovy</h3>
<p><a href="http://groovy.codehaus.org/">Groovy</a> is "multiple dispatch". The example for Java works perfectly in Groovy as expected. It is so intuitive.</p>
<pre class="code">TouchEventHandler h = new MyTouchEventHandler();
h.handle(new TouchStartEvent()); // prints "touch started :)"
</pre>
<p>The type of the parameters are detected dynamically and handle(TouchStartEvent) is called. I'll explain more details. Groovy replaces the method call with a CallSite object that has the caller class, the index for the call, and the method name. It is like this by expressing in code.</p>
<pre class="code">TouchEventHandler h = new MyTouchEventHandler();
CallSite handleN = // create a call site for the "n:handle"
handleN.call(h, new TouchStartEvent());
</pre>
<p>CallSite searches the target method gradually by listing up the meta data of "handle" methods of MyTouchEventHandler and checking the number and the type of the parameters. Of course this dynamic resolution comes at a cost but CallSite caches the method and will call the method immediately at the second time. Recent Groovy has @StaticCompile that is an annotation for turning off dynamic capabilities. Where use the annotation is compiled to binary that doesn't use CallSites and calls methods statically. In that case "multiple dispatch" doesn't work.</p>
<h3>Others</h3>
<p>I checked a bit about "multiple dispatch" support of other JVM languages. It is seemed that Clojure has "defmulti" macro corresponds to "dispatch" keyword of Xtend. Scala doesn't support but they might say that it's unnecessary because of powerful pattern matching. JRuby and Jython don't support because Ruby and Python don't support it. I'm wondering also about Kotlin but I'll end this post here because I'm full :-P </p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com6tag:blogger.com,1999:blog-8493386468030365259.post-25377322736110474152012-09-02T02:33:00.000-07:002012-09-02T11:30:18.323-07:00SmileyFX: Smiley for JavaFX<p>Smiley ☺ is often used in graphical programs. SmileyFX is a library that allows to easily create Smiley in <a href="http://www.oracle.com/technetwork/java/javafx">JavaFX</a>. You can make a Smiley just as follows using SmileyFX:</p>
<pre class="code">
Node smiley = SmileyFX.smiley(40);
</pre>
<p>That's it! The code creates a 40 pixel diameter (<i>20x20xπ pixels</i>) Smiley. Here is a perfect example in <a href="http://www.oracle.com/technetwork/java/javafx">JavaFX</a> and <a href="http://groovyfx.org/">GroovyFX</a>:</p>
<pre class="code">
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.stage.Stage;
import smileyfx.SmileyFX;
public class JavaFXDemo extends Application {
@Override
public void start(Stage stage) throws Exception {
Node smiley = SmileyFX.smiley(40);
Scene canvas = SceneBuilder.create()
.root(new Group(smiley))
.width(160)
.height(160)
.build();
// center align
smiley.layoutXProperty().bind(
canvas.widthProperty()
.subtract(smiley.getLayoutBounds().getWidth())
.divide(2));
smiley.layoutYProperty().bind(
canvas.heightProperty()
.subtract(smiley.getLayoutBounds().getHeight())
.divide(2));
// scale by window resize
smiley.scaleXProperty().bind(
canvas.widthProperty()
.divide(canvas.getWidth()));
smiley.scaleYProperty().bind(
canvas.heightProperty()
.divide(canvas.getHeight()));
stage.setScene(canvas);
stage.setTitle("Smiley FX");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
</pre>
<pre class="code">
import static groovyx.javafx.GroovyFX.start
import static smileyfx.SmileyFX.smiley
start {
stage(title: "Smiley FX", visible: true) {
scene(id: "canvas", width: 160, height: 160) {
node(smiley(40)).with {
// center align
layoutXProperty().bind((canvas.width() - layoutBounds.width)/2)
layoutYProperty().bind((canvas.height() - layoutBounds.height)/2)
// scale by window resize
scaleXProperty().bind(canvas.width()/canvas.width)
scaleYProperty().bind(canvas.height()/canvas.height)
}
}
}
}
</pre>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga27OSXtmDh18Yyl9SQkmjWgK91HbenO1-PlTDmSOwohXwy57Ih_36Bsr9YnyzihK0LhEAkB1u6P_H1OVcUEPVEgk0K5_F6rLTWe5OGuZpY_8RFQ46vVMnSC_RpILmqRv0DI87mZRoWRtF/s1600/Screen+Shot+2012-09-02+at+5.07.42+PM.png" imageanchor="1" style=""><img border="0" height="296" width="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga27OSXtmDh18Yyl9SQkmjWgK91HbenO1-PlTDmSOwohXwy57Ih_36Bsr9YnyzihK0LhEAkB1u6P_H1OVcUEPVEgk0K5_F6rLTWe5OGuZpY_8RFQ46vVMnSC_RpILmqRv0DI87mZRoWRtF/s400/Screen+Shot+2012-09-02+at+5.07.42+PM.png" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkPG8gk9dC48AHHN6LTrNlY6PDncAEhsjNb-YaMJM9VB0TeBbS5_cWeeNSXkjBKvVW631FpYhy4redxltztHnwg0rWNu08sS01M2E0qbnIVwAyQHbCVE09RHUQ31GHR-7V5byEnOfnrOwK/s1600/Screen+Shot+2012-09-02+at+5.30.34+PM.png" imageanchor="1" style=""><img border="0" height="244" width="333" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkPG8gk9dC48AHHN6LTrNlY6PDncAEhsjNb-YaMJM9VB0TeBbS5_cWeeNSXkjBKvVW631FpYhy4redxltztHnwg0rWNu08sS01M2E0qbnIVwAyQHbCVE09RHUQ31GHR-7V5byEnOfnrOwK/s400/Screen+Shot+2012-09-02+at+5.30.34+PM.png" /></a></div>
<p>
SmileyFX is available in <a href="http://code.google.com/p/smileyfx/">here</a>. You can use it by the follow steps:</p>
<ol>
<li>git clone https://code.google.com/p/smileyfx/</li>
<li>cd smileyfx && ant dist</li>
</ol>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com2tag:blogger.com,1999:blog-8493386468030365259.post-10095460792187111282012-07-06T13:30:00.000-07:002012-07-06T13:38:08.530-07:00GBench 0.3.1 released!<p>Today I released <a href="http://code.google.com/p/gbench/">GBench 0.3.1</a> with one bug fix for <a href="http://groovy.codehaus.org/">Groovy 2.0</a>.</p>
<p>Release note: <a href="http://code.google.com/p/gbench/wiki/ReleaseNotes031">http://code.google.com/p/gbench/wiki/ReleaseNotes031</a>.</p>
Here is an example that compares execution time with and without @CompileStatic (new feature of Groovy 2.0) using GBench:
<pre class="code">
@Grab('com.googlecode.gbench:gbench:0.3.1-groovy-2.0')
import gbench.BenchmarkBuilder
import groovy.transform.CompileStatic
int fib(int n) {
if (n < 2) return n
return fib(n - 1) + fib(n - 2)
}
@CompileStatic
int fib2(int n) {
if (n < 2) return n
return fib2(n - 1) + fib2(n - 2)
}
new BenchmarkBuilder().run {
int n = 20
"Normal Version" { fib n }
"@CompileStatic Version" { fib2 n }
}.prettyPrint()
</pre>
The output of the example:
<pre class="code">
Environment
===========
* Groovy: 2.0.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (23.0-b21, Oracle Corporation)
* JRE: 1.7.0_04
* Total Memory: 98.25 MB
* Maximum Memory: 1157.375 MB
* OS: Mac OS X (10.7.4, x86_64)
Options
=======
* Warm Up: Auto
* CPU Time Measurement: On
user system cpu real
Normal Version 89945 14 89959 89961
@CompileStatic Version 39219 4 39223 39222
</pre>
</p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com6tag:blogger.com,1999:blog-8493386468030365259.post-59790859040587579732012-05-09T10:44:00.000-07:002012-05-10T17:42:57.474-07:00Restart Groovy life with Invokedynamic<p>Groovy supported invokedynamic (indy) in version 2.0 beta 3 that was released on May 7. This is a short post just to show you how to restart your Groovy life with indy. Indy is a new bytecode instruction of Java SE 7 for dynamic method invocation. If you don't know about indy, read its <a href="http://jcp.org/en/jsr/detail?id=292">JSR</a>. </p>
<p>Okay, let's start. First of all, install an indy-supported version of Groovy. Because indy is not supported by default for now (2.0 beta 3). You can choose which of the following ways:</p>
<p>* Download an archive and use a groovy-indy.jar or groovy-all-indy.jar in indy/ instead of groovy.jar in lib/ or groovy-all.jar in embeddable/.</p>
<p>* Build from source with an option to enable indy.</p>
<pre class="code">
ant install -DuseIndy=true -DskipTests=true
</pre>
<br/>
<p>Second, compile with an option to enable indy in a way that meets your needs as follows:</p>
<p>* groovy</p>
<pre class="code">
groovy --indy YourScript.groovy
</pre>
<p>* groovyc</p>
<pre class="code">
groovyc --indy YourScript.groovy
</pre>
<p>* GroovyShell class</p>
<pre class="code">
import org.codehaus.groovy.control.CompilerConfiguration
def conf = new CompilerConfiguration()
conf.optimizationOptions.indy = true
def shell = new GroovyShell(conf)
shell.evaluate(/* your script */)
</pre>
<br/>
<p>That's all! Have a nice Groovy life!</p>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com4tag:blogger.com,1999:blog-8493386468030365259.post-46444101069254682112012-05-04T12:14:00.001-07:002012-05-06T22:00:27.720-07:00Exploring JavaFX 2 - Accessing application parametersJavaFX provides Application.getParameters() as a way to access application parameters from an Application class object. For example, if a user sets a width and a height as the options and a message as an argument in GNU format:
<pre class="code">
java AccessApplicationParametersDemo --width=200 --height=100 hello
</pre>
the application can receive the parameters as follows:
<pre class="code">
public class AccessApplicationParametersDemo {
public static void main(String[] args) {
Application.launch(UsingGetParametersApplication.class, args);
}
}
</pre>
<pre class="code">
public class UsingGetParametersApplication extends Application {
@Override
public void start(Stage stage) throws Exception {
Map<String, String> opts = getParameters().getNamed();
System.out.println("width=" + opts.get("width"));
System.out.println("height=" + opts.get("height"));
List<String> args = getParameters().getUnnamed();
System.out.println("message=" + args.get(0));
}
}
</pre>
But getParameters() is not functional for now (v2.2-b06) because the option parser is poor. It does not support short form options and POSIX format and it does not allow any of the following formats:
<pre class="code">
-w=200 -h=100
</pre>
<pre class="code">
--width 200 --height 100
</pre>
<pre class="code">
-w 200 -h 100
</pre>
Should I customize getParemters()? What do you do if you hear accessing the implementation class is hard coded in it and the method is final? I mean, it is not good choice to get options or arguments directly from getParameters() for now. I recommend that you let getParameters() to act a transporter and ask <a href="http://commons.apache.org/cli/">Apache Commons CLI</a> to take the main work:
<pre class="code">
public class UsingCommonsCliApplication extends Application {
@Override
public void start(Stage stage) throws Exception {
Options options = new Options();
options.addOption("w", "width", true, "");
options.addOption("h", "height", true, "");
CommandLineParser parser = new PosixParser();
CommandLine cmd = parser.parse(
options,
getParameters().getRaw().toArray(
new String[getParameters().getRaw().size()]
)
);
System.out.println("width=" + cmd.getOptionValue("width"));
System.out.println("height=" + cmd.getOptionValue("height"));
System.out.println("message=" + cmd.getArgList().get(0));
}
}
</pre>
The problem might will be solved sooner or later because <a href="http://javafx-jira.kenai.com/browse/RT-21342">JavaFX team's answer to the problem is "We could consider this for a future version"</a>. In the first place, such a feature must be needed only by Applet or JWS that receives parameters in the fixed format, thus it seems better that JavaFX has application classes for those environments like AppletApplication or JWSApplication and make only them to have the feature.Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-172500740323331162012-03-24T06:53:00.007-07:002012-04-01T18:49:06.554-07:00Right Groovy BenchmarkingBenchmarking Groovy or other languages that run on JVM is difficult and if you do it without much thought you will get wrong results. For example, I assume that I wrote the following program for comparing performances of StringBuilder and StringBuffer. It is well known that StringBuffer is slower because of synchronization:<br />
<pre class="code">def n = 100 * 1000
def at, bt
bt = System.nanoTime()
n.times {
def sb = new StringBuilder()
sb.append('foo')
sb.append('bar')
sb.append('baz')
}
at = System.nanoTime()
println((at - bt) / n)
bt = System.nanoTime()
n.times {
def sb = new StringBuffer()
sb.append('foo')
sb.append('bar')
sb.append('baz')
}
at = System.nanoTime()
println((at - bt) / n)
</pre><br />
But the result was against expectation. StringBuffer is more than twice as fast as StringBuilder (Groovy 1.8.6、JVM 1.7.0_04-ea Server VM). It must be worse than or equal to StringBuilder even if the cost of synchronization had been written off by optimization. It means this measurement completely failed.<br />
<pre class="code">StringBuilder 1947.3 (2.76)
StringBuffer 703.1 (1)
</pre><br />
The failure was more obvious by comparing between StringBuilders:<br />
<pre class="code">StringBuilder #1 2030.68 (4.85)
StringBuilder #2 418.47 (1)
</pre><br />
The changes of the execution times shows us what the problem was. Some optimizations had been finished in the first time measurement and the second time measurement had started from where the optimizations were finished. Thus, the first time has a disadvantage. And there is an outstanding value in the second time measurement. The value is because of garbage collection and garbage that was collected at this time include garbage which was generated during the first time measurement. Thus, conversely, the second time has a disadvantage at this point. It means right benchmarking is what making measurements to stand on the same start line and thus we need to have finish optimization and memory cleaning before measuring.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhirn0IemBShP8y4V0ItbzNXUMT6wNhLn_YIsI0IQkQ4k4uy1TMNd1dsh9Fxir8U5Q9aqISmJkVPPobnBNgqaJQuiHKQVXr2V0bC38VMlfMCJL_Pv3AP-rfq0Xr83mLabw15MUeVTXLJzRt/s1600/benchmark_stringbuilder_stringbuilder.png" imageanchor="1"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhirn0IemBShP8y4V0ItbzNXUMT6wNhLn_YIsI0IQkQ4k4uy1TMNd1dsh9Fxir8U5Q9aqISmJkVPPobnBNgqaJQuiHKQVXr2V0bC38VMlfMCJL_Pv3AP-rfq0Xr83mLabw15MUeVTXLJzRt/s640/benchmark_stringbuilder_stringbuilder.png" width="640" /></a></div><br />
Solving the problems by yourself is OK, but there is a benchmarking framework for Groovy, <a href="http://code.google.com/p/gbench/">GBench</a>. GBench 0.3.0 has got a feature to solve that tiresome problems and get correct results in place of you. The following code is a rewrite using GBench. You can get a simple report that shows only execution time by setting measureCpuTime to false for disabling measurement of CPU time:<br />
<pre class="code">import gbench.*
new BenchmarkBuilder().run(measureCpuTime:false) {
'StringBuilder' {
def sb = new StringBuilder()
sb.append('foo')
sb.append('bar')
sb.append('baz')
sb.toString()
}
'StringBuffer' {
def sb = new StringBuffer()
sb.append('foo')
sb.append('bar')
sb.append('baz')
sb.toString()
}
}.prettyPrint()
</pre><br />
The result of the code was as follows. Why the difference was not so much is because my environment is Server VM and operations of locking were optimized. Jeroen Borgers' article <a href="http://www.infoq.com/articles/java-threading-optimizations-p1">Do Java 6 threading optimizations actually work?</a> is a good reference for optimizations around locking:<br />
<pre class="code">StringBuilder 244 (1)
StringBuffer 265 (1.08)
</pre><br />
The result of the same code with disabling the optimizations (-XX:-DoEscapeAnalysis -XX:-EliminateLocks -XX:-UseBiasedLocking) was as follows:<br />
<pre class="code">StringBuilder 242 (1)
StringBuffer 310 (1.28)
</pre>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-62797570219189371632011-10-13T22:39:00.000-07:002012-05-04T18:46:17.807-07:00A way to write Groovy's AST easily<span class="section-title">It is hard to write AST</span><br />
<br />
Groovy provides a DSL to generate AST for implementation of AST transformation. But the DSL is complicated and hard to learn. Let's assume that you want to generate AST of GString:<br />
<pre class="code">"Hi, $name."
</pre>In this case, the DSL will be the following. Who can remember this stuff as many as the syntax?<br />
<pre class="code">gString 'Hi, $name.', {
strings {
constant 'Hi, '
constant '.'
}
values {
variable 'name'
}
}
</pre><br />
AST is also can be generated from code, but it does not benefit from the compiler checking (<a href="http://joesgroovyblog.blogspot.com/2011/10/ast-transformation-using-astbuilder.html">Joachim Baumann explains about it</a>) and performance is less than the DSL. Please see the following benchmark:<br />
<pre class="code">@Grab('com.googlecode.gbench:gbench:0.2.2')
import gbench.BenchmarkBuilder
import org.codehaus.groovy.ast.builder.AstBuilder
def benchmarks = new BenchmarkBuilder().run {
'DSL to AST' {
new AstBuilder().buildFromSpec {
gString 'Hi, $name.', {
strings {
constant 'Hi, '
constant '.'
}
values {
variable 'name'
}
}
}
}
'Code to AST' {
new AstBuilder().buildFromString('"Hi, $name"')
}
}
benchmarks.prettyPrint()
</pre><pre class="code"><!-- -->
user system cpu real
DSL to AST 0 0 0 339918
Code to AST 0 0 0 2076590
</pre>So at the end of the day, you will cheat implementation code or test code of the DSL while writing AST. I believe that you can easily imagine it is a hard work.<br />
<br />
<span class="section-title">How can we write the DSL easily?</span><br />
<br />
I created a library that automatically generates the DSL from code to resolve the problem. The library, named AstSpecBuilder is now available <a href="http://code.google.com/p/groovy-astspecbuilder/">here</a>. The usage is very simple, just pass code to build method:<br />
<pre class="code">import astspecbuilder.*
def spec = new AstSpecBuilder().build('"Hi, $name."')
def expectedSpec = '''\
block {
returnStatement {
gString 'Hi, $name.', {
strings {
constant 'Hi, '
constant '.'
}
values {
variable 'name'
}
}
}
}
'''
assert expectedSpec == spec
</pre>It also can generate the DSL from AST, or rather the method in the above example is just a shortcut for the following code:<br />
<pre class="code">import astspecbuilder.*
def ast = new AstBuilder.buildFromString('"Hi, $name."')
def spec = new AstSpecBuilder().build(ast)
</pre><br />
The indent string is 4 spaces by default but it has an option to change it. In the following example, the DSL will be indented with a tab:<br />
<pre class="code">def spec = new AstSpecBuilder(indent: '\t').build('"foo"')
def expectedSpec = '''\
block {
\treturnStatement {
\t\tconstant 'foo'
\t}
}
'''
assert expectedSpec == spec
</pre>Masato Nagaihttp://www.blogger.com/profile/12532119746926511346noreply@blogger.com2tag:blogger.com,1999:blog-8493386468030365259.post-5712105037248750502011-07-20T20:35:00.000-07:002011-07-24T12:01:23.677-07:00GBench 0.2.0 released<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I released </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><a href="http://code.google.com/p/gbench/">GBench 0.2.0</a></span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> today. GBench is a benchmarking framework for Groovy. This framework allows you to easily benchmark for Groovy programs by providing two powerful features, an AST transformation and a builder.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><b>What's New</b></span><br />
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Added support for CPU time.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Improved the builder API.</span></li>
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Added better (Groovier) syntax to add benchmark target code blocks.</span></li>
</ul></ul><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> ----</span><br />
<div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">run {</span><br />
<div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> with 'label', {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> -></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> ----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">run {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> label {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<ul><ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Added new options for run().</span></li>
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">"average", "idle", "trim". See its javadoc for usage. Thanks to Yasuharu Nakano (author of <a href="http://kobo.github.com/groovyserv/">GroovyServ</a>) for providing the source code.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">"repeat". This option is an alternative to "time" option, but "time" option still available for backward compatibility.</span></li>
</ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Added new APIs.</span></li>
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">sum(), average(), prettyPrint(). See their javadoc for usage.</span></li>
</ul></ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Changed versioning scheme.</span></li>
</ul><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> YY.MM.DD </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> -> </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> Major.Minor.Micro</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><b>Resolved Issues</b></span><br />
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The name of the system property to specify @Benchmark's default handling contains the old domain.</span></li>
</ul><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> "groovybenchmark.sf.net.defaulthandle"</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> -> </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> "gbench.defaulthandle"</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><b>Examples</b></span><br />
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">AST transformation Example:</span></li>
</ul><script src="https://gist.github.com/1096271.js?file=gistfile1.gradle">
</script><br />
<ul><li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Builder Example:</span></li>
</ul><script src="https://gist.github.com/1096278.js?file=gistfile1.gradle">
</script><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Please try and let me know your feedback (via this blog's comment, </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><a href="http://code.google.com/p/gbench/issues/list">the project's issue tracking system</a></span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">, or Twitter:@nagai_masato). Your feedback helps GBench to continue to impove.</span></div></div>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8493386468030365259.post-90033953802560940802011-07-10T07:57:00.000-07:002011-07-13T00:18:33.944-07:00GBench available on Maven Central!<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I'm happy to announce that <a href="http://code.google.com/p/gbench/">GBench</a> 11.07.05 is now available on the Maven Central Repository. It means that </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">you can use GBench via Grape. Please try GBench and let me know your feedback!</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<script src="https://gist.github.com/1074566.js?file=gistfile1.gradle">
</script><br />
<script src="https://gist.github.com/1074571.js?file=gistfile1.gradle">
</script>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-91405454727115084712011-07-04T23:41:00.000-07:002011-07-04T23:41:48.542-07:00GBench project moved to Google Code!<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I moved GBench project hosting over Google Code. </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><a href="http://code.google.com/p/gbench/">http://code.google.com/p/gbench/</a></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">GBench is a benchmarking framework for Groovy. </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Please go to the site and try GBench!</span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-91677460625549746702011-07-03T09:52:00.000-07:002011-07-03T09:52:24.348-07:00Groovy Quiz: How many Elvises are there?<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">How many Elvises are there?:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">[]?.size?:[].@size?:[]*.size?:[].&size?':[].size?':[]</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8493386468030365259.post-4896992267538731512011-07-02T08:09:00.001-07:002012-03-29T20:14:18.842-07:00Poison for Groovy Part 2<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Unfortunately, I had success in generating a new poison for Groovy today (I already found another poison. Please read <a href="http://nagaimasato.blogspot.com/2011/05/warning-s-are-toxic-to-groovybats.html">my previous post</a>). </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">There are three steps to generate it:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">1. Get a Windows machine which has Groovy is installed in it. This is a VERY HARD mission.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">2. Set JAVA_OPTS environment variable with a double-quoted string has a space character:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">> set JAVA_OPTS=-Daprop="a value"</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">3. Run groovy:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">> groovy -h</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Then you'll get the follwing error:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">value"" was unexpected at this time.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I already reported two issues related to this bug and provided patches for them (See <a href="http://jira.codehaus.org/browse/GROOVY-4910">GROOVY-4910</a> and <a href="https://jira.codehaus.org/browse/GANT-126">GANT-126</a></span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">). </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I hope these issues will be resolved soon, </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Windows-specific issues are always left unresolved even if they have patches, though. </span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Groovy is a cross-platform language that runs on a virtual machine, right?</span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8493386468030365259.post-45457361547124232282011-06-25T17:21:00.000-07:002011-07-05T00:38:04.007-07:00GBench = @Benchmark Annotation + BenchmarkBuilder<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I released <b>GBench</b>,<b> </b>a benchmarking framework for Groovy. Now GBench has two features, <b>@Benchmark Annotation</b> and <b>BenchmarkBuilder</b>. @Benchmark Annotation is an annotation that allows to measure execution time of methods without modifying production code and is already published. Please read <a href="http://nagaimasato.blogspot.com/2011/06/benchmark-annotation-for-groovy-gets.html">the previous post</a> for more detail information. BenchmarkBuilder is a convenient builder to write benchmark code easily and now appears for the first time.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The following code is an example to get benchmark string concatenation by repeating them 1000 times:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">def strings = ['GBench', ' = ', '@Benchmark Annotation', ' + ', 'BenchmarkBuilder']</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">def benchmark = new BenchmarkBuilder()</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">benchmark.run times: 1000, {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> with '+=', { </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> def s = ''</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> for (string in strings) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> s += string </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> with 'concat', { </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> def s = ''</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> for (string in strings) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> s.concat string </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> with 'string builder', {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> def sb = new StringBuilder() </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> for (string in strings) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> sb << string </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> sb.toString() </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> with 'join', {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> strings.join()</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">println benchmark</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The output will be like this:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span> time</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">+= <span class="Apple-tab-span" style="white-space: pre;"> </span>18197705</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">concat <span class="Apple-tab-span" style="white-space: pre;"> </span> 7669621</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">string builder<span class="Apple-tab-span" style="white-space: pre;"> </span> 9420539</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">join <span class="Apple-tab-span" style="white-space: pre;"> </span> 5248348</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Of course you can sort the results:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">println benchmark.sort({ lhs, rhs -> lhs.time <=> rhs.time })</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span> time</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">join <span class="Apple-tab-span" style="white-space: pre;"> </span> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">5248348</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">concat <span class="Apple-tab-span" style="white-space: pre;"> </span> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">7669621</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">string builder<span class="Apple-tab-span" style="white-space: pre;"> </span> </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">9420539</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">+= <span class="Apple-tab-span" style="white-space: pre;"> </span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">18197705</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">and also you can handle the results as you want!:</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">new File('benchmark.csv').withWriter { file -></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> file.writeLine 'label,time(ms)'</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> benchmark.sort().each { bm -></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> file.writeLine "${bm.label},${bm.time / 1000000}"</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">> cat benchmark.csv</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">label,time(ms)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">join,</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">5.248348</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">concat,</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">7.669621</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">string builder,</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">9.420539</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">+=,</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">18.197705</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">----</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">For now, GBench can measure only wall-clock time but I'm planning to also support CPU time and user time in a future release.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">You can download GBench from <a href="http://code.google.com/p/gbench/">here</a>. Please try and let me know your feedback!</span>Unknownnoreply@blogger.com1