Ah, OK, thank you all. Now I get results similar to David for (a) including definitions and benchmark code in the same file, and (b) using the declarations:
(declare (standard-bindings) (extended-bindings) (block) (not safe))
frying-pan:~/Desktop/oop-bench> gsi -:m100000 class-benchmark (class-direct-instance-creation .003332853317260742) (class-constructor-instance-creation .9427149295806885) (class-access .006258964538574219) (class-modif .00386810302734375) (class-dispatch-2 .7867801189422607) (class-dispatch-5 1.447295904159546) (class-polymorhpic-dispatch-2 2.3654139041900635) (class-polymorhpic-dispatch-5 5.206311225891113)
frying-pan:~/Desktop/oop-bench> gsi -:m100000 define-type-benchmark (define-type-instance-creation .003023862838745117) (define-type-access .004261016845703125) (define-type-modif .004247903823852539) (define-type-dispatch-2 .06431698799133301) (define-type-dispatch-5 .21142292022705078) (define-type-polymorhpic-dispatch-2 .10065913200378418) (define-type-polymorhpic-dispatch-5 .2658059597015381)
frying-pan:~/Desktop/oop-bench> gsi++ -:m100000 meroon-benchmark [ Meroon V3 Paques2001+1 $Revision: 1.1 $ ] (meroon-instance-creation .07878613471984863) (meroon-constructor-instance-creation .07859683036804199) (meroon-access .05495786666870117) (meroon-modif .048612117767333984) (meroon-dispatch-2 .24296903610229492) (meroon-dispatch-5 .27795886993408203) (meroon-polymorhpic-dispatch-2 .25885701179504395) (meroon-polymorhpic-dispatch-5 .3787720203399658)
I was trying to figure out what "new" in class.scm does different from just make-*; it appears to call a constructor (if one is available) for certain fields. I think that's what the "instantiate" macro is intended to do in Meroon; if an explicit value is not given for a slot, then it calls a constructor. So I included a benchmark for making an instance using the "instantiate" macro (which doesn't make any difference for these simple classes).
I think I understand why Meroon is noticeably slower for a number of operations:
1. As part of each instance creation, Meroon calls the initialize! generic on the newly created instance. That's a cross-trampoline call to a generic, in this case for a no-op.
2. Each access and modification is "safe", in that it checks whether its argument is of the same class (or of a subclass). This is also a cross-trampoline call to a generic. I suppose it might be better if the Gambit compiler exposed the declarations to the macro-expander, so one could change the macro expansion of define-class to choose whether to insert the checks based on the current declaration of (safe) or (not safe).
3. The Meroon runtime is not in the same file, so that affects dispatch.
Thanks for the interesting benchmarks.
Brad