Version française
Home     About     Download     Resources     Contact us    
Browse thread
OCaml troll on Slashdot
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Oliver Bandel <oliver@f...>
Subject: Re: [Caml-list] OCaml troll on Slashdot
On Tue, Mar 15, 2005 at 04:07:37PM -0700, William D.Neumann wrote:
> On Mar 15, 2005, at 3:12 PM, Yoann Padioleau wrote:
> 
> >>To which, I'd assume the majority response would be, "So?"
> >
> >So some of his arguments are right. You make object "So?" but
> >we could continue a long moment that way.
> 
> Perhaps, perhaps not.  His point seems to be that programming in a 
> "functional style"[1] is inherently slower than an imperative style 
> because a list or a map have different performance characteristics than 
> do arrays.  To which the only response is along the lines of "True.  


Well, I tested the program with the original values for
columnSize and numRows as well as differet values.
I did not used the values that are mentioned in the posting
(7x3), because I had not too much time.

But with

  let columnSize = 5;;
  and with
  let numRows = 7;;

(look at the ";;" it seems he had used it in the toplevel... :))

and ocamlprof I got stuff like that:




================================================
(* checks if each cell in center colum is covered by an empty cell *)
let rec isCovered c1 c2 c3 =
  (* 2650588 *) let 
          memoized_isCovered = memoize3 isCovered_table isCovered 
  in 
  match (c1, c2, c3) with
   (* if center runs out of cells first, we are covered *)
        | (_, [], _) -> (* 501290 *) true
   (* if others run out first, we are not covered *)
        | ([], _, _) -> (* 0 *) false
        | (_, _, []) -> (* 0 *) false
   (* Empty followed by Planted in center colum
      skip this cell and next cell *)
        | ( (_::(_::rest1)), (Empty::(Planted::rest2)), (_::(_::rest3)) ) -> 
                (* 553730 *) true && ( isCovered rest1 rest2 rest3 )

        | ( (Empty::rest1), (_::rest2), (_::rest3) ) -> 
                (* 837698 *) true && ( isCovered rest1 rest2 rest3 )

        | ( (_::rest1), (_::rest2), (Empty::rest3) ) -> 
                  (* 291720 *) true && ( isCovered rest1 rest2 rest3 )

   (* Empty followed by Empty in center
      This cell is covered, but don't skip next cell *)
        | ( (_::rest1), (Empty::rest2), (_::rest3) ) -> 
                (* 297530 *) true && ( isCovered rest1 rest2 rest3 )
   (* this cell is covered by next cell *)
        | ( (_::rest1), (Planted::(Empty::rest2)), (_::rest3) ) -> 
                (* 99282 *) true && ( isCovered rest1 (Empty::rest2) rest3 )

   (* default:  we reach this if our current cell is not covered *)
        | (_, _, _) -> (* 69338 *) false;;
================================================


which does not really looks tail recursive.

Called more than 2 * 10^6 times...

And many other examples...


e.g. this one:

(* applies a list of functions to an argument *)
let rec applyFunctionList functions argument =
  (* 267386 *) match functions with
        | [] -> (* 9782 *) []
        | f::rest -> (* 257604 *) (f argument)::(applyFunctionList rest argument);; 

"only" called 267386 times, but when looking how the arguments
are used:  also applyFunctionList is not tail recursive...
...and even if called less than 10^6 times... it's a function that
creates a list in a non-tailrec way.

IMHO this is the reason, why the program performs so badly!

Ths stuff of tail recursion - even if it took a while
until I got it - was one of the first things on this list,
that people told me that it is necessary....

...but as a *real* C++ programmer it seems it is not necessary to learn...
...and better use the energy to tell all people how badly OCaml
performs!

Well... he performs badly in code-writing. :->

If he had read this mailing list, he wouls have seen that HE
(better: the code he wrote) is/was the problem, not OCaml itself. :)


Ciao,
   Oliver