ikvm?

317 views
Skip to first unread message

Raoul Duke

unread,
Jul 12, 2008, 4:52:10 PM7/12/08
to clo...@googlegroups.com
i see by way of some chat transcripts that Clojure has been run on
.Net via IKVM. does anybody have a cheat sheet howto for doing that?
and any notes on how to call .Net libraries?

muchas gracias.

Shawn Hoover

unread,
Jul 14, 2008, 7:11:32 PM7/14/08
to clo...@googlegroups.com

I was able to run the REPL by following the basic tutorial (http://www.ikvm.net/userguide/tutorial.html) and using clojure.jar. You can download IKVM and use ikvm.exe as a replacement for java.exe (to use the Windows binary names).

ikvm -cp clojure.jar clojure.lang.Repl

Also ikvmc had no problem compiling clojure.jar to clojure.exe.

To access .NET libraries, first use ikvmstub to generate stubs of the .NET dll you want to call, and then use Clojure's Java interop features to instantiate objects. Check the "Develop a .NET Application in Java" section of the tutorial.

# ikvmstub mscorlib.dll
# ikvm -cp clojure.jar;mscorlib.jar clojure.lang.Repl
user=> (import '(cli.System.Collections Stack))
user=> (def s (Stack.))
#'user/s
user=> s
System.Collections.Stack
user=> (. s (get_Count))
0
user=> (. s (Push (ref [])))
nil
user=> (. s (get_Count))
1
user=>

Shawn

Raoul Duke

unread,
Jul 14, 2008, 7:44:29 PM7/14/08
to clo...@googlegroups.com
> I was able to run the REPL by following the basic tutorial

w00t. thanks! must try...

Shawn Hoover

unread,
Jul 18, 2008, 9:24:14 PM7/18/08
to clo...@googlegroups.com
I found some corrections to make in my IKVM example from the other day...


On Mon, Jul 14, 2008 at 4:11 PM, Shawn Hoover <shawn....@gmail.com> wrote:
To access .NET libraries, first use ikvmstub to generate stubs of the .NET dll you want to call, and then use Clojure's Java interop features to instantiate objects. Check the "Develop a .NET Application in Java" section of the tutorial.
<snip>
# ikvmstub mscorlib.dll
# ikvm -cp clojure.jar;mscorlib.jar clojure.lang.Repl
user=> (import '(cli.System.Collections Stack))
user=> (def s (Stack.))
#'user/s
user=> s
System.Collections.Stack

For the record there is no need to generate mscorlib.jar and add it to the classpath. The point was to coerce ikvm to reference and load mscorlib.dll, but ikvm being a .NET program obviously already references mscorlib and loads it at runtime. However, the technique of adding a stub jar to the ikvm classpath is correct for making your own assemblies or other framework assemblies available to clojure. Make the stub, add it to your classpath, and you're ready to import from cli.*. (IKVM requires the cli. to prevent namespace clashes between .NET and Java classes.)

Aside: The jar stub generation step is also necessary if you want to import .NET classes into Java sources which you then compile with javac and run with ikvm. The stub jar has to be there for javac to make sense of things when compiling your sources. Then when you compile your jar to .NET, ikvmc sees the stub dependency and swaps in a reference to the actual .NET assembly. .NET, Java, and Clojure all in one app? That's getting a little complicated... but clojure and IKVM make it easy if you want to do it!

There's one technique that requires no stub generation. When you compile clojure.jar to clojure.exe (or clojure.dll) with ikvmc, you can use a command line switch to add a reference to a .NET assembly. No stub jar is needed, and in clojure the import cli.* calls work as before. For example:

# ikvmc -reference:RunManager.dll clojure.jar
Note IKVMC0004: using main class "clojure.lang.Repl" based on jar manifest
Note IKVMC0002: output file is "clojure.exe"
# clojure.exe
Clojure
user=> (import '(cli.Xia.AlphaGui.RunManager HandelWrapAlpha))
nil
user=> (. HandelWrapAlpha GetHandelAlpha)
Xia.AlphaGui.RunManager.HandelWrapAlpha

This is cool because the ikvmstub step isn't needed, but it is admittedly less dynamic than just tweaking the classpath.

Shawn

raould

unread,
Jul 24, 2008, 2:34:39 AM7/24/08
to Clojure
i am experimenting with ikvm + clojure and it seems like it sure takes
a long time for things to run. using "java" it takes 4 seconds to fire
up clojure.lang.Script helloworld.clj, but with ikvm it is 16 seconds.
have other folks trying out ikvm run into similar overhead? not sure
how it works as programs get larger, if it is just an initial overhead
or if it gets even worse.

i am perhaps somewhat loathe to admit it, but the c sharp command line
complier is so darned fast, it is really nice, too bad it is c
sharp...

sincerely.
P.S.: any chance perhaps someday in the future of maybe somehow doing
a non-exiting reusable version of the Script compiler, to avoid having
to repeatedly pay Java startup costs?

Chas Emerick

unread,
Jul 24, 2008, 8:01:28 AM7/24/08
to Clojure
The last time I used ikvm (as opposed to ikvmc) was some years ago,
but it was certainly slow to ramp up then. That's just the price you
pay for the flexibility to use Java libraries in .NET at runtime.

On the other hand, you can roll up a clojure Repl or Script .exe using
ikvmc, and it'll run *really* fast.

- Chas

Raoul Duke

unread,
Jul 24, 2008, 12:19:14 PM7/24/08
to clo...@googlegroups.com
> On the other hand, you can roll up a clojure Repl or Script .exe using
> ikvmc, and it'll run *really* fast.

oh! right! thanks for the clue, i'd been only looking at ikvm and
ikvmstub so far.

Shawn Hoover

unread,
Jul 24, 2008, 12:55:31 PM7/24/08
to clo...@googlegroups.com

I've seen relative results similar to Raoul's, but I didn't see a difference in performance whether I used ikvmc or just ikvm. In both cases clojure startup took about 4x as long in .NET compared to java. This was intuitive considering clojure's compiler has to generate java bytecode and then IKVM has to compile that to MSIL. However, ANTS Profiler shows most of the time was spent in analyze and analyzeSeq in the compiler. I couldn't narrow it down any more than that. Perhaps the type checks in analyze are slower in .NET?

I expected .NET to catch up to java with the message-around-a-ring demo, on the assumptions that threading would be the bottleneck and that both java and .NET would end up using the same OS threading APIs. Most of the time was spent dealing with Monitors (according to ANTS), but  .NET was again 2-8x slower.

foo2 from the java_interop docs (http://clojure.org/java_interop) was also 2-8x slower in .NET.

In summary, after profiling and looking at the ikvmc-compiled code in Reflector, it's not clear why things are that much slower. Is the JVM just that good?

Shawn
Reply all
Reply to author
Forward
0 new messages