

print . length . lines =<< getContents



getContents



#include "stdio.h"



int main()

{

int i = 0;

int last = 0;

while (last = getchar() != EOF) {

if (last == '

')

i++;

}

if (last == '

')

i--;

printf("%i

", i);

return 0;

}



getchar

getContents

lines

length

* This is building on from last time . In particular, that means that all the same disclaimers apply.Having done "wc -c" as the previous benchmark, the next thing to look at is "wc -l" - line counting. A line is defined as being a sequence of non-newline characters, optionally ending with a newline. This means that "test" has 1 line, "test

" has 1 line, "test

test" has 2 lines. Its trivial to express this in Haskell:The Haskell code uses the sameas before, but the C code needed more changes:The C code is quite hard to write. In fact, this code is the original version I wrote - with an accidental mistake. Rest assured that I benchmarked with the correct code, but see if you can spot the mistake.As in the previous example, I've demanded that all implementations useat their heart, to make everything a fair comparison. The benchmark was then line counting on the same 35Mb file as previously:And the numbers: C=4.969, Supero=5.063, GHC=9.533. This time the difference between C and Supero is a mere 2%. However the difference between Supero and GHC has grown considerably! The reason for this is an advanced optimisation that has managed to removethe intermediate lists. In a normal Haskell program,would build a list of characters,would take that list, and build a list of strings, thenwould take that list and consume it. With my optimisation, no intermediate lists are created at all.While in the previous benchmark it was easy to examine and understand the generated GHC Core, for this one it is much harder. The benchmark has ended up using a recursive group of functions, none of which use unboxed numbers. For this reason, I suspect that the benchmark could be improved further for Supero. Once again, credit needs to be given to GHC for the results - it is clearly doing some clever things.This benchmark is slightly more interesting than the previous one, but is still a bit of a micro-benchmark - not following a real program. My next task is to probably move on to "wc -w" to complete then set, then a real benchmark suite such as nobench. I hope that this demonstrates that Haskell can be beautiful, pure, and match C for speed in some cases.