Hi! Compiling (display "Hello world\n") to an individual executable file generates a ~3MB executable.
What are the strategies available to get Gambit application binary sizes down as much as possible, for applications to be distributed to client machines, with a particular designated purpose?
Can parts of the Gambit core somehow be taken away, such as (eval) support, flonum support, arithmetical functions?
Is there any strategy using which one can compile Scheme code to binary form, in a way that only the functions used in the code is included in the binary? I.e. smaller binary for (display "Hello world\n") than for an application that uses cos, eval, open-tcp-client.
Thanks Mikael
Afficher les réponses par date
Currently there are only two (related) ways to get a smaller executable:
1) Use shared libraries. That is, compile the Gambit runtime to a shared library (./configure --enable-shared). Then executables will be really small; a "hello world" program will be a few kB.
2) Compile your program to a .o1 file (or a set of .o1 files). Then start gsi and ask it to load these files, for example: gsi mod1.o1 mod2.o1 main.o1 . Of course you can put that in a shell script.
I've thought about implementing a "tree-shaker" solution which would be closer to what you want. It would require that the whole runtime be compiled with your program. This would not only allow the compiler to eliminate dead code, it would eliminate the need for intermodule jumps and thus improve performance. I'm not planning to try this anytime soon but it should not be too hard to do, so if the need arises I may reconsider.
Marc
On 3-Oct-08, at 12:24 PM, Mikael More wrote:
Hi!
Compiling (display "Hello world\n") to an individual executable file generates a ~3MB executable.
What are the strategies available to get Gambit application binary sizes down as much as possible, for applications to be distributed to client machines, with a particular designated purpose?
Can parts of the Gambit core somehow be taken away, such as (eval) support, flonum support, arithmetical functions?
Is there any strategy using which one can compile Scheme code to binary form, in a way that only the functions used in the code is included in the binary? I.e. smaller binary for (display "Hello world \n") than for an application that uses cos, eval, open-tcp-client.
Thanks Mikael
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
"MF" == Marc Feeley feeley@iro.umontreal.ca writes:
MF> I've thought about implementing a "tree-shaker" solution which MF> would be closer to what you want. It would require that the MF> whole runtime be compiled with your program. This would not MF> only allow the compiler to eliminate dead code, it would MF> eliminate the need for intermodule jumps and thus improve MF> performance.
I'll put my vote in for this one right now. I was just thinking of how I could do this with one of my applications earlier today.
Joel
On Fri, Oct 3, 2008 at 6:59 PM, Marc Feeley feeley@iro.umontreal.ca wrote:
I've thought about implementing a "tree-shaker" solution which would be closer to what you want. ... I'm not planning to try this anytime soon but it should not be too hard to do
I've had the same feeling at least half-a-dozen times over the last 10 or 15 years ever since I first encountered a tree-shaker for Smalltalk image-size reduction. Fortunately the hardware guys have kept ahead of my urge to reduce resource usage, and I've never quite gotten around to implementing a shake pass for S2 - which was one of my goals for writing it in the first place.
IIRC, Stalin shakes the tree, but then you have to live with the Stalin dialect as well (which I don't have a problem with, but not everybody feels that way).
david rush
On 3-Oct-08, at 1:59 PM, Marc Feeley wrote:
Currently there are only two (related) ways to get a smaller executable:
Actually there is another one, which consists in eliminating the whole Gambit library, except for the "essentials" (lib/_kernel.scm and some of the C files in lib/ which implement the GC, C-interface, initialization code, etc).
Using this technique (see trace below) I managed to build a 300 kB executable on MacOS X from the v4.2.9 tarball. This could be reduced some more by removing some functionality. Anyway, this is just a quick-and-dirty experiment.
The downside of course is that you have to implement yourself whatever you need in your application. You only have very basic functionality (the inlinable primitives like ##fx+, ##cons, ##car). This is like reinventing the wheel... but I'm sure some users will appreciate the hack value!
Marc
% tar zxf gambc-v4_2_9.tgz % cd gambc-v4_2_9 % ./configure --enable-single-host % make bootstrap % ################ Now edit lib/makefile.in . % diff lib/makefile.in lib/makefile.in-orig < MODULES = _kernel < MODULES_SCM = _kernel.scm < MODULES_C = _kernel.c < MODULES_O = _kernel@obj@ < MODULES_O_PLUS = +_kernel@obj@ < MODULES_O_COMMA = _kernel@obj@ ---
MODULES = _kernel _system _num _std \ _eval _io _nonstd _thread _repl MODULES_SCM = _kernel.scm _system.scm _num.scm _std.scm \ _eval.scm _io.scm _nonstd.scm _thread.scm _repl.scm MODULES_C = _kernel.c _system.c _num.c _std.c \ _eval.c _io.c _nonstd.c _thread.c _repl.c MODULES_O = _kernel@obj@ _system@obj@ _num@obj@ _std@obj@ \ _eval@obj@ _io@obj@ _nonstd@obj@ _thread@obj@ _repl@obj@ MODULES_O_PLUS = +_kernel@obj@ +_system@obj@ +_num@obj@ +_std@obj@ \ +_eval@obj@ +_io@obj@ +_nonstd@obj@ +_thread@obj@ +_repl@obj@ MODULES_O_COMMA = _kernel@obj@,_system@obj@,_num@obj@,_std@obj@,\ +_eval@obj@,_io@obj@,_nonstd@obj@,_thread@obj@,_repl@obj@
81c87,88 < MODULES_O_IN_COMPILE_ORDER = _kernel@obj@ ---
MODULES_O_IN_COMPILE_ORDER = _io@obj@ _num@obj@ _std@obj@ \ _kernel@obj@ _nonstd@obj@ _repl@obj@ _eval@obj@ _thread@obj@
_system@obj@ % make clean % make making all in include ... making all in lib ... ../gsc-comp -:=.. -f -link -flat -o _gambc.c _kernel.c *** WARNING -- "##*" is not defined, *** referenced in: ("_kernel.c") *** WARNING -- "##+" is not defined, *** referenced in: ("_kernel.c") *** WARNING -- "##map" is not defined, *** referenced in: ("_kernel.c") *** WARNING -- "##string->symbol" is not defined, *** referenced in: ("_kernel.c") % ################ Note that lib/_kernel.scm depends on some Gambit % ################ library procedures that are not defined in % ################ lib/_kernel.scm. This will be fixed so that % ################ lib/_kernel.scm is self contained, as it should. % ################ Now create hw.scm . % cat hw.scm ;; Make sure the compiler does not assume the standard library is ;; linked in. (declare (block) (not inline) (not inline-primitives) (inlining-limit 0) (not run-time-bindings) )
;; Supply the procedures lib/_kernel.scm needs (this dependency should ;; be removed since it is gratuitous). (define (##map f lst) '()) ;; I'm lazy (define (##string->symbol str) 'foo) (define (##+ x y) 0) (define (##* x y) 0)
;; The "hello world" program:
(c-declare "#include <stdio.h>")
(define puts (c-lambda (char-string) int "puts"))
(puts "hello world") % ./gsc-comp -:=. -c hw.scm % ./gsc-comp -:=. -link hw.c % gcc -Iinclude -D___SINGLE_HOST hw_.c hw.c lib/libgambc.a -o hw % strip hw % ls -l hw -rwxr-xr-x 1 feeley feeley 300384 Oct 4 09:22 hw % ./hw hello world
On Oct 3, 2008, at 12:24 PM, Mikael More wrote:
Is there any strategy using which one can compile Scheme code to binary form, in a way that only the functions used in the code is included in the binary? I.e. smaller binary for (display "Hello world\n") than for an application that uses cos, eval, open-tcp- client.
If, after a "make bootstrap" you change the line
(##define-macro (use-fast-bignum-algorithms) #t)
in lib/_num.scm to
(##define-macro (use-fast-bignum-algorithms) #f)
then you should reduce the executable size by some amount (I forget how much).
Brad
On Oct 4, 2008, at 2:51 AM, Bradley Lucier wrote:
On Oct 3, 2008, at 12:24 PM, Mikael More wrote:
Is there any strategy using which one can compile Scheme code to binary form, in a way that only the functions used in the code is included in the binary? I.e. smaller binary for (display "Hello world\n") than for an application that uses cos, eval, open-tcp- client.
If, after a "make bootstrap" you change the line
(##define-macro (use-fast-bignum-algorithms) #t)
in lib/_num.scm to
(##define-macro (use-fast-bignum-algorithms) #f)
and then do another "make"
then you should reduce the executable size by some amount (I forget how much).
Brad