jaroslaw
jaroslaw

Reputation: 23

haskell processing so much faster than C# (codeeval)

I'm doing some challenges on codeeval and I was shocked when I saw results. Haskell results tend to be several times faster than C# solutions. I know both languages are different but can anyone explain to me (as simple as possible) why the difference is so big? Is it haskell superiority or just codeeval fault?

Some examples: challenge: odd numbers, time (ms): haskell -> 1, C# -> 123

C# using System; using System.IO;

class Program
{
    static void Main(string[] args)
    {
         for(int i=1;i<=99;i++)
            {
            if(i%2==1) Console.WriteLine(i);
            }
    }
}

Haskell

main = do
    putStrLn $ init . drop 1 . replace ',' '\n' . show . filter odd $ [1..99]


replace :: Char -> Char -> String -> String
replace c1 c2 line = map (\letter -> if letter==c1 then c2 else letter) line

challenge: reverse words, time: haskell -> 2, C# -> 166

challenge: sum of digits, time: haskell -> 1, C# -> 168

challenge: swap numbers, time: haskell -> 7, C# -> 355

Upvotes: 2

Views: 264

Answers (1)

Random Dev
Random Dev

Reputation: 52280

for C# it is your Console.WriteLine:

this one:

    var timer = new Stopwatch();
    timer.Start();
    var sb = new StringBuilder();
    for (int i = 1; i <= 99; i++)
    {
        if (i%2 == 1) sb.AppendLine(i.ToString());
    }
    Console.Write(sb.ToString());
    timer.Stop();
    Console.WriteLine("took {0:0.0}ms", timer.Elapsed.TotalMilliseconds);

takes 1-2ms on in release on my machine, yours take around 10ms

For their site it might take even longer, depending on what they do with the output.

Aside from this C#'s generated code will still be interpreted by some runtime, so you might even measure the initialization/startup as well

Haskell might probably not (although they might just runhaskell as well ...(?))

I guess you have to ask the support from CodeEval for details.


LINQ style

back to around 10ms but closer to Haskell

    var numbers =
        String.Join("\n",
        Enumerable
            .Range(1, 99)
            .Where(i => i%2 == 1)
            .Select(i => i.ToString()));

    Console.WriteLine(numbers);

some fun / performance tests

I extended the range to 9999 with this in eshell time ./prg.exe (yeah I'm on windows right now :( ):

  • your original Haskell version with ghc -O2: about 0.72s
  • the Stringbuilder version I posted above compiled to release: around 0.87

quite close IMO

here with 99999:

  • C# 8.2s
  • Haskell: 8.2s

so no worry they seem to be very close ;)

But I am not surprised at all - in the end all you do is print something to the console - so it should only depend on your OS/machine.

The other problems might be more interesting but I am to lazy to write code for them

Upvotes: 7

Related Questions