AliasSeq seems to compile slightly faster with static foreach

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Jan 8 02:20:44 UTC 2018


On Friday, January 05, 2018 06:10:25 Jonathan M Davis via Digitalmars-d 
wrote:
> There was a recent PR for Phobos where Seb added static to a bunch of
> foreach's that used AliasSeq. It hadn't actually occurred to me that that
> was legal (I've basically just been using static foreach where foreach
> with AliasSeq doesn't work), but it is legal (which I suppose isn't
> surprising when you think about it; I just hadn't). However, that got me
> to wondering if such a change was purely aesthetic or whether it might
> actually have an impact on build times - particularly since running dub
> test for one of my recent projects keeps taking longer and longer. So, I
> added static to a bunch of foreach's over AliasSeqs in that project to
> see if it would have any effect. The result was that dub test went from
> about 16.5 seconds on my system to about 15.8 seconds - and that's just
> by adding static to the foreach's over AliasSeqs, not fundamentally
> changing what any of the code did. That's not a huge speed up, but it's
> definitely something and far more than I was expecting.
>
> Of course, you have to be careful with such a change, because static
> foreach doesn't introduce a new scope, and double braces are potentially
> required where they weren't before, but given that I'd very much like to
> streamline that test build, adding static to those foreach's was
> surprisingly worthwhile.
>
> Taking it a step further, I tried switching some of the static foreach's
> over to using array literals, since they held values rather than types,
> and that seemed to have minimal impact on the time to run dub test.
> However, by switching to using std.range.only, it suddenly was taking
> more like 11.8 seconds. So, with a few small changes, I cut the time to
> run dub test down by almost a third.

LOL. Okay, I feel like an idiot now. Switching to static foreach resulted in
a slight speed-up, and then switching to only resulted in a very large
speed-up. However, it turns out that the main reason that I got the speed-up
that I did with only was because I screwed up.

In a number of places, I was using only by itself, but in a bunch of places,
I was using only with lockstep and iota so that I could have indices, and I
screwed up with the iota call. I misremembered how iota worked with a single
argument; I thought that iota(0) created an infinite range, whereas it
creates a zero-length range. Once I fixed it so that it was
iota(size_t.max), it was actually slightly slower than using array literals.
So, while I definitely got a speed-up by switching away from using normal
foreach with AliasSeq, ultimately, the really large speed-up I got by
switching to only was because I was accidentally not even compiling in large
sections of test code. :|

So, that explains why only was behaving so much more efficiently than folks
like Timon thought that it should.

So, based on what I'm seeing, I'd still recommend using static foreach with
either AliasSeq or array literals over using normal foreach with an
AliasSeq, but using only is pointless. I was just being dumb in how I used
it, and the result was not only a useless speed-up in compilation, but once
I wrote more tests using iota incorrectly (as opposed to the ones that were
compiled in and working before my changes), I thought that I was properly
testing code whereas I wasn't testing anything at all. :|

Oh well, live and learn, I guess.

- Jonathan M Davis



More information about the Digitalmars-d mailing list