Ticket #180 (new defect)

Opened 10 years ago

Last modified 6 years ago

Optimization: Speed up use of literal collections

Reported by: Chuck Owned by:
Priority: minor Milestone:
Component: Cobra Compiler Version: 0.8.0
Keywords: optimization Cc:


The program below demonstrates that Cobra's naive handling of something like:

if s in ['a', 'b'], ...

is rather slow. This creates a burden on the developer to write lower level code to get better performance.

use System.Diagnostics

class P

	def main
		reps = 10_000_000
		s = 'a'
		sw = Stopwatch()
		for i in reps
			if s in ['a', 'b', 'c', 'd', 'e', 'f']
				s = 'a'
		dur1 = sw.elapsedMilliseconds
		t = ['a', 'b', 'c', 'd', 'e', 'f']
		for i in reps
			if s in t
			# if s in List<of String>(t)
				s = 'a'
		dur2 = sw.elapsedMilliseconds
		ratio = dur1 / dur2
		trace dur1, dur2, ratio


dur1=16482 (Int64);
dur2=464 (Int64);
ratio=35.521551724137931034482758621 (Decimal);
at x-literal-list.cobra:27; in P.main

Change History

Changed 6 years ago by hopscc

I fiddled a bit with this a while ago by adding a cache for the last created (in this case) List literal and reusing it if the next literal to be created is the same.

It seemed that the overhead of my determination of whether the current literal is 'the same' is about equivalent (or worse) to literal construction overhead ( walk list generating combined hashcode for contents)....
perhaps theres a better way of determining 'same' - comparison to same AST node as last construction ??

Also perhaps the comparison is a little bogus since the second piece above is the more correct (performant wise) way of doing literal comparisons anyway.
Construction (of anything literal or not) within a loop is generally a bad-thing for performance - hoisting the construction out of the loop isnt really low-level coding, just common sense if you are concerned with micro performance.

Interesting to see if using .Net 4.0 construction literal codegen is appreciably faster.

Changed 6 years ago by Charles

I agree that hoisting out of the loop is an obvious technique, but that doesn't mean that I want to do it manually. And for small collections, the code is more readable when the collection is in the loop.

Btw the technique that I had in mind was that if there was an InExpr? and a collection literal containing only collection literals, constants and primitive literals ('foo', 5), then the compiler could hoist the literal out to a shared member.

Note: See TracTickets for help on using tickets.