gmpl/FsControl — pull request #20 by atifaziz (2014-03-30 13:16:38+00:00)
Title: Recursive splitBy with tail calls

Clearer implementation without requiring ref/cells although it is (unfortunately) some 18% slower and causing nearly 3 times more gen 0 collections. Here are 10 runs for the existing `while` loop version:

Real: 00:00:00.427, CPU: 00:00:00.453, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.431, CPU: 00:00:00.484, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.437, CPU: 00:00:00.500, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.422, CPU: 00:00:00.484, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.432, CPU: 00:00:00.468, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.429, CPU: 00:00:00.484, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.424, CPU: 00:00:00.437, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.429, CPU: 00:00:00.484, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.419, CPU: 00:00:00.453, GC gen0: 15, gen1: 6, gen2: 1
Real: 00:00:00.422, CPU: 00:00:00.453, GC gen0: 15, gen1: 6, gen2: 1

Here are 10 runs for the recursive version:

Real: 00:00:00.508, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.525, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.520, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.533, CPU: 00:00:00.531, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.522, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.525, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.517, CPU: 00:00:00.500, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.521, CPU: 00:00:00.531, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.516, CPU: 00:00:00.500, GC gen0: 43, gen1: 5, gen2: 1
Real: 00:00:00.527, CPU: 00:00:00.515, GC gen0: 43, gen1: 5, gen2: 1

The above numbers are for 32-bit version of F# 3.0. The Mono (F# 2.0) version is twice as slow as well as, I believe, the F# 3.0 64-bit version on .NET though I don't have the numbers for the latter handy.

Why am I still proposing this version? It's clearer, and well, you asked. :) Perhaps both versions can be maintained and one selected in favour of the other based on a conditional compilation flag until a time when the compiler and JIT improves to not have such pronounced differences.