I typed up my answer. I was ready to post. I hit preview, and... Araq beat me by a few minutes! Oh well, maybe this post would still have some value...
* * * I get similar results: the perl program is about three times faster. OK, let's `use Time::HiRes`, `import times` [(etc)](https://gist.github.com/lbmn/d424dd0c8c85fa195743356fc133235a) for some ad-hoc time-subtracting. About 24.5% of the Nim program's execution time is spent on `surface.write_to_png image`, which is actually a bit faster than Perl, so the cairo bindings are not the problem. About 75% of the Nim program's execution time is spent on `draw(level, t1)`. That proc uses recurses multiple times (level 12 to 3), but it uses about 69% of the total program time when level is 4, in which case the loop is executed 6561 times. So let's zoom in on this loop... **Wowzers, 88% of the time in that inner loop is spent just on concatenating seqs! So that is our problem...** I don't know what the best solution is, but one [step in the right direction](https://gist.github.com/lbmn/32f20a60e8cc4b5157c9a94fa3adcafc) would be to allocate next before the for loop in draw(): var next: trias = newSeq[trian]() And to use add inside the loop: next.add @[ (HEAD, left, right), (left, LEFT, tail), (right, tail, RIGHT) ] And now we're 18% faster than perl.
