Passback variable performance comparison

by Colin LeMahieu (modified: 2009 Nov 18)

These tests test the allocation performance of 3 passback variable options and the subsequent access time when retrieving the value back from the calling function.

The difficulty in a general solution arises with void safety. CELL needs to have an initial value provided upon creation, for a complex type a dummy value may not be an option so a detachable type would be used with the default value initialized to void. TUPLE isn't currently void-safe though in the future the thinking is that TUPLE will need default initialization similar to CELL. The performance hit would then be on the retrieval needing to go through an object test. SPECIAL has the unique property of being able to have an attached type without an initializer. Note there are 10x more retrieval attempts than allocations in order to get a descent time sample; allocation is by far the slower process.

Test setup:

  • ES version 6.5.8.1550
  • Finalized
  • Complete void-safety
  • Types attached by default

Results:test_1 CELL allocation: 21.259, 21.159, 21.206

test_2 TUPLE allocation:24.490, 24.483, 24.514

test_3 SPECIAL allocation:22.502, 22.515, 22.553

test_4 CELL access:10.613, 10.571, 10.572

test_5 TUPLE access:12.901, 12.841, 12.837

test_6 SPECIAL access:13.642, 13.572, 13.580

test_7 CELL access no object test:10.614, 10.590, 10.584

Allocation (greater is faster)CELL > SPECIAL > TUPLE

Access (greater is faster)CELL > TUPLE > SPECIAL

Allocation time is a factor of 20 slower than access so over all CELL is the fastest when used as a single creation single passback context. All of these options are very close in performance to each other and realistically shouldn't make a difference.

It's unusual that SPECIAL would have a slower access time than an object check with CELL or TUPLE.

feature make do test_1 end test_1 local i: INTEGER do from i := 0 until i > 100_000_000 loop test_cell i := i + 1 end end test_2 local i: INTEGER do from i := 0 until i > 100_000_000 loop test_tuple i := i + 1 end end test_3 local i: INTEGER do from i := 0 until i > 100_000_000 loop test_special i := i + 1 end end test_4 local r0: CELL [detachable CELL [NATURAL_32]] r1: CELL [detachable CELL [NATURAL_32]] i: INTEGER val: detachable CELL [NATURAL_32] val_2: NATURAL_32 do create r0.put (Void) create r1.put (Void) sub_ddmmss_cell (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) from i := 0 until i > 1_000_000_000 loop val := r0.item if attached {CELL [NATURAL_32]} val as val_l then val_2 := val_l.item end val := r1.item if attached {CELL [NATURAL_32]} val as val_l then val_2 := val_l.item end i := i + 1 end end test_5 local r0: TUPLE [r0: detachable CELL [NATURAL_32]] r1: TUPLE [r1: detachable CELL [NATURAL_32]] i: INTEGER val: detachable CELL [NATURAL_32] val_2: NATURAL_32 do create r0 create r1 sub_ddmmss_tuple (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) from i := 0 until i > 1_000_000_000 loop val := r0.r0 if attached {CELL [NATURAL_32]} val as val_l then val_2 := val_l.item end val := r1.r1 if attached {CELL [NATURAL_32]} val as val_l then val_2 := val_l.item end i := i + 1 end end test_6 local r0: SPECIAL [CELL [NATURAL_32]] r1: SPECIAL [CELL [NATURAL_32]] i: INTEGER val_2: NATURAL_32 do create r0.make_empty (1) create r1.make_empty (1) sub_ddmmss_special (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) from i := 0 until i > 1_000_000_000 loop val_2 := r0 [0].item val_2 := r1 [0].item i := i + 1 end end test_7 local r0: CELL [detachable CELL [NATURAL_32]] r1: CELL [detachable CELL [NATURAL_32]] i: INTEGER val: NATURAL_32 do create r0.put (Void) create r1.put (Void) sub_ddmmss_cell (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) from i := 0 until i > 1_000_000_000 loop val := r0.item.item val := r1.item.item i := i + 1 end end test_cell local r0: CELL [detachable CELL [NATURAL_32]] r1: CELL [detachable CELL [NATURAL_32]] do create r0.put (Void) create r1.put (Void) sub_ddmmss_cell (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) end test_tuple local r0: TUPLE [r0: detachable CELL [NATURAL_32]] r1: TUPLE [r1: detachable CELL [NATURAL_32]] do create r0 create r1 sub_ddmmss_tuple (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) end test_special local r0: SPECIAL [CELL [NATURAL_32]] r1: SPECIAL [CELL [NATURAL_32]] do create r0.make_empty (1) create r1.make_empty (1) sub_ddmmss_special (r0, r1, 0x55bf739f, 0xc3945435, 0x0fff167f, 0xf3e8e754) end sub_ddmmss_cell (sh: CELL [detachable CELL [NATURAL_32]]; sl: CELL [detachable CELL [NATURAL_32]]; ah: NATURAL_32; al: NATURAL_32; bh: NATURAL_32; bl: NATURAL_32) local x: NATURAL_32 do x := al - bl sh.put (create {CELL [NATURAL_32]}.put (ah - bh - (al < bl).to_integer.to_natural_32)) sl.put (create {CELL [NATURAL_32]}.put (x)) end sub_ddmmss_tuple (sh: TUPLE [sh: detachable CELL [NATURAL_32]]; sl: TUPLE [sl: detachable CELL [NATURAL_32]]; ah: NATURAL_32; al: NATURAL_32; bh: NATURAL_32; bl: NATURAL_32) local x: NATURAL_32 do x := al - bl sh.sh := create {CELL [NATURAL_32]}.put (ah - bh - (al < bl).to_integer.to_natural_32) sl.sl := create {CELL [NATURAL_32]}.put (x) end sub_ddmmss_special (sh: SPECIAL [CELL [NATURAL_32]]; sl: SPECIAL [CELL [NATURAL_32]]; ah: NATURAL_32; al: NATURAL_32; bh: NATURAL_32; bl: NATURAL_32) local x: NATURAL_32 do x := al - bl sh.force (create {CELL [NATURAL_32]}.put (ah - bh - (al < bl).to_integer.to_natural_32), 0) sl.force (create {CELL [NATURAL_32]}.put (x), 0) end

Update: Replaced extend' in special test with more realistic force'. This makes CELL with an object test the fastest option.

Update: Added test_7 which tests accessing cell without an object test. This compared to test_4 with an object test shows object tests are negligible performance hits when the test always is true.