tags:

views:

1042

answers:

7

Are there any good ways to make small haskell executables? With ghc6 a simple hello world program seems to come to about 370kB (523kB before strip). Hello world in C is about 4kB (9kB before strip).

+3  A: 

You should count your blessings (370Kb? Luuuxury) :

bash$ sbcl
This is SBCL 1.0.24, an implementation of ANSI Common Lisp.

* (sb-ext:save-lisp-and-die "my.core")
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into ./my.core:
...
done]
bash$ du -sh my.core 
 25M    my.core
bash$ 

Seriously though while you can probably shake out haskell binaries a bit, it's really not a fair comparison with C. There's a more going on there.

Last time I played with ghc (and this might be out of date) it was statically linking everything, which will be a factor.

simon
+10  A: 

GHC is statically linking everything (except libraries used by runtime itself, which are linked dynamically).

In the old ages, GHC linked the whole (hsakell) library in as soon as you've used something from it. Sometime ago, GHC started to link "per obj file", which drastically reduced the binary size. Judging from the size, you must'vebeen used the newer GHC already.

On the plus side, you aready have a lot of stuff in those 500K, like mulithreaded core, garbage collector etc.

Add at least garbage collector to your C code, then compare them again :)

ADEpt
While it is true that the Haskell binary contains a lot of stuff the C binary does not, it's pointless to have it if it isn't used...
Lars Wirzenius
@liw.fi If you are /that/ worried about the size of your executables, C is the only language good enough for you.
Rayne
@liw.fi Haskell is almost by definition about garbage collection, multi-core execution etc. So, in fact, it is pointless _not_ to have all that stuff in the core. Or leave it out (pouring additional effort into modularized core that could do just so). And for what? To save 100K of binary size?
ADEpt
+5  A: 
strip -p --strip-unneeded --remove-section=.comment -o your_executable_small your_executable

also try looking at ldd -dr your_executable

Dan
+9  A: 

The size you're seeing is the Haskell runtime (libHSrts.a), which is statically linked into every Haskell executable. If it were a shared object, like librt.o for C, your binary would be only a few k (the size of a split .o file in the library source).

Short of implementing dynamic linking of libHSrts.a on your platform, you can make your executables smaller via strip.

Don Stewart
+5  A: 

Things are changing - keep an eye on this ongoing piece of work.

Ganesh Sittampalam
+2  A: 

If the size of your binary really matters, you can use the tool gzexe that pack an (preferably already stripped) executable with the gzip compression. On my 64-bit Linux box, the original hello world program takes 552 KB, after stripping 393 KB, and after stripping and gzipping 125 KB. The darker side of gzipping is in performance -- the executable has to be unpacked first.

dqd
+1  A: 

With the development branch of GHC (anyone know exactly which version this was added in?):

$ ghc -o hello hello.hs
$ strip -p --strip-unneeded --remove-section=.comment -o hello-small hello
$ du hello hello-small
700 hello
476 hello-small

Add the -dymamic flag for a dynamically linked RTS:

$ ghc -dynamic -o hello hello.hs
$ strip -p --strip-unneeded --remove-section=.comment -o hello-small hello
$ du hello hello-small
24  hello
16  hello-small

http://hackage.haskell.org/trac/ghc/wiki/SharedLibraries/PlatformSupport

For comparison with C:

$ gcc hello.c -o hello
$ strip -p --strip-unneeded --remove-section=.comment -o hello-small hello
$ du hello hello-small
12  hello
8    hello-small
Caleb Case