RE: Bagley shootout. Was: Lightningspeed haskell

A String is a [Char] and a Char is a heap object. So a file represented as a string takes a massive 20 bytes/char (12 for the cons cell, 8 for the Char cell). Then it's all sucked through several functions. It's entirely possible, though, that the biggest performance hit is in the I/O itself. We'd be happy if anyone wanted to invesigate and improve. Simon | -----Original Message----- | From: John Atwood [mailto:atwoodj@cs.orst.edu] | Sent: 02 March 2001 01:12 | To: Josef Svenningsson | Cc: glasgow-haskell-users@haskell.org | Subject: Bagley shootout. Was: Lightningspeed haskell | | | I notice that the reverse file program, while concise, is quite slow. | The program in its entirety is: | main = interact $ unlines . reverse . lines | | Any thoughts on why its time is 5.68 seconds, vs 3.56 for tcl, 2 for | perl, 0.19 for gcc, 0.18 for ocaml; and how it might be sped | up? Is the | lack of speed all in the stdio I/O? | | Is there a way to tell which benchmarks have no haskell entry? | | John Atwood | -- | | Josef Svenningsson wrote: | > | > Hi all. | > | > Some days ago someone posted this url: | > http://www.bagley.org/~doug/shootout/ | > | > which is a page benchmarking a number of different languages and | > compilers where ghc is one of them. Some benchmarks lacked a haskell | > versions (and some still do) and so I decided to fill in | some of the gaps. | > | > One benchmark turned out to give pretty remarkable results. It's the | > producer/consumer benchmark. I suggest you all take a look | at it. The | > haskell version is six (SIX!!!) times faster than the c | version. Hey, | > what's going on here? I would really like to hear some | comments from our | > dear implementors. | > | > It should be noted that synchronisation is achieved by using | > slightly different kinds of primitives. But still... six times... | > | > I lift my hat of for the ghc-implementors. | > | > /Josef | > | > | > _______________________________________________ | > Glasgow-haskell-users mailing list | > Glasgow-haskell-users@haskell.org | > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users | > | | | _______________________________________________ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users |

Simon Peyton-Jones wrote:
A String is a [Char] and a Char is a heap object. So a file represented as a string takes a massive 20 bytes/char (12 for the cons cell, 8 for the Char cell). Then it's all sucked through several functions.
It's entirely possible, though, that the biggest performance hit is in the I/O itself. We'd be happy if anyone wanted to invesigate and improve.
Unless ghc is extremely fast at filling a heap, it's the memory allocation. I get 11.8 seconds for ghc with a standard heap and 7.3 seconds when I give it enough heap not to do garbage collection. Since this is 200M, I don't think there is much time to do anything else. The input is 2000000 bytes. So, this would be 40M worth of [Char] data, I guess lines and unlines make ehm 12*2*2=48M, so that's about 100M total. I guess the other 100M is used for function applications. Jan

A feature I have always wanted in ghc was the ability to compile a program with NO heap allocator/ GC whatsoever. basically I want the program to grab large chunks of memory from the OS with 'sbrk (or mmap or whatever) and just give out pieces of it as they are requested. no GC, no keeping track of whats been allocated, just increment a pointer to the new allocation point and return the old one.. I want this for a number of reasons: it would be useful when figuring out what the cost of the heap overhead is, it would be something of a control case when comparing algorithms. believe it or not, never freeing anything or keeping track of memory is a valid GC tactic when you can guarentee your program will run in a finite amount of time and perform a finite amount of heap allocations in order to acomplish its task (and your OS properly cleans up when processies exit). (think simple preprocessors, read, modify, spit out, exit., or mathematical programs which may take a long time to run but eventually terminate with a useful result. (testing primality of a single number perhaps)) I imagine a good portion of the size of resulting executeables is in the runtime support routines. it could be used to create ultra small programs if most of the runtime could be omitted. it would be neat to play with. just a random thought. John On Fri, Mar 02, 2001 at 11:26:06AM +0100, Jan Kort wrote:
Unless ghc is extremely fast at filling a heap, it's the memory allocation. I get 11.8 seconds for ghc with a standard heap and 7.3 seconds when I give it enough heap not to do garbage collection. Since this is 200M, I don't think there is much time to do anything else. The input is 2000000 bytes. So, this would be 40M worth of [Char] data, I guess lines and unlines make ehm 12*2*2=48M, so that's about 100M total. I guess the other 100M is used for function applications.
-- -------------------------------------------------------------- John Meacham http://www.ugcs.caltech.edu/~john/ California Institute of Technology, Alum. john@foo.net --------------------------------------------------------------

Reducing the 46M reported on the shootout without changing the program would be interesting. An easy way for improvement would be to share characters and small integers like is done in Hugs. This would mean the initial list of characters would be reduced from 40M to 24M, so the total should go down from 46M to 30M. Reducing the 200M would be much harder, even with changing the program I can't get lower than 120M: f :: String -> String -> String f ys [] = ys f ys ('\n':xs) = '\n':ys ++ (f [] xs) f ys (x:xs) = f (x:ys) xs main :: IO() main = interact $ reverse . (f []) Jan
participants (3)
-
Jan Kort
-
John Meacham
-
Simon Peyton-Jones