articlePassback variable performance comparison

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:= 0
			until
				i > 100_000_000
			loop
				test_cell
				i := i + 1
			end
		end
 
	test_2
		local
			i: INTEGER
		do
			from:= 0
			until
				i > 100_000_000
			loop
				test_tuple
				i := i + 1
			end
		end
 
	test_3
		local
			i: INTEGER
		do
			from:= 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:= 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 + 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:= 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 + 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:= 0
			until
				i > 1_000_000_000
			loop
				val_2 := r0 [0].item
				val_2 := r1 [0].item:= 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:= 0
			until
				i > 1_000_000_000
			loop
				val := r0.item.item
				val := r1.item.item:= 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:= 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:= 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:= 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.

Syndicate content