Working character by character in Haskell
Andre W B Furtado
awfurtado@uol.com.br
Fri, 19 Oct 2001 03:14:42 -0300
Humn... I agree with both of you, Albert and Tom. I started it from the
beginning, using map and don't using reverse anymore. But the C program is
still 7x faster than the Haskell one. Here is the code of the Haskell
program:
main :: IO ()
main = do
bmFile <- openFileEx "in.txt" (BinaryMode ReadMode)
bmString <- hGetContents bmFile
writeFile "out.txt" (map inc bmString)
hClose bmFile
inc :: Char -> Char
inc a = toEnum ((fromEnum a) + 1)
And now the C program:
#include <stdio.h>
void main()
{
FILE *in, *out;
char ch;
in = fopen("in.txt","rb");
out = fopen("out.txt","wb");
while ( (ch=getc(in)) != EOF)
putc(ch + 1,out);
fclose(out);
fclose(in);
}
As you noticed, the main idea here is to increment the character by "one".
Is the Haskell program now a nice translation of the C program? If it is (I
think so...) why is the C program so much faster than it?
Thanks again,
-- Andre
----- Original Message -----
From: Albert Lai <trebla@vex.net>
To: <glasgow-haskell-users@haskell.org>
Sent: Thursday, October 18, 2001 9:42 PM
Subject: Re: Working character by character in Haskell
> "Andre W B Furtado" <awfurtado@uol.com.br> writes:
>
> [...]
>
> > For example, suppose function doSomeStuffWith returns its own parameter.
> > Using a 1.5MB file in this case, the Haskell program ends in almost 5
> > seconds, while the C program ends in less than 0.5 seconds... Is my
Haskell
> > program too bad implemented? (I'm using GHC 4.08-1 under a Windows 98
> > platform.)
>
> I indeed think that your Haskell program is inefficient and is not a
> translation of your C program. It reverses a huge string, which takes
> not only execution time but also garbage collection time and memory,
> which entails even more time for OS overhead and swapping out other
> things in the physical memory.
>
> (Many programmers complain "my linear-time algorithm takes just 1
> second on a 100M list, so why is it taking 5 seconds on a 200M list?"
> They forget that because of issues such as cache locality and virtual
> memory, their computers do not scale.)
>
> I am wondering that if doSomeStuffWith is pure-functional, why are you
> writing and using copyFile instead of just using map? I mean:
>
> main :: IO ()
> main = do
> bmFile <- openFileEx "in.txt" (BinaryMode ReadMode)
> bmString <- hGetContents bmFile
> writeFile "out.txt" (map doSomestuffWith bmString)
> hClose bmFile
>
> Because both hGetContents and map are lazy and use O(1) memory, this
> program behaves exactly as your C program plus occasional garbage
> collections that don't hurt too much. In partcular, the OS will see
> no difference (although the cache does).