caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Thomas Fischbacher <tf@functionality.de>
To: "Quôc Peyrot" <chojin@lrde.epita.fr>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] The Implicit Accumulator: a design pattern using optional arguments
Date: Wed, 27 Jun 2007 14:55:53 +0100	[thread overview]
Message-ID: <46826C69.5060802@functionality.de> (raw)
In-Reply-To: <1A1D6F56-B3DB-4552-969C-9859482175AC@lrde.epita.fr>

Quôc Peyrot wrote:

> It's funny that you speak about this, because I recently (few days  ago) 
> used
> a pattern similar to yours, but to actually improve performances.
> I had something like that (which is quite different than my actual  
> code, but
> the idea is the same):
> 
> let encrypt str =
>   let len = String.length str in
>   let encrypted = String.create len in
>   (* ... *)
>   encrypted

vs.

 > let encrypt ?encrypted str =
 >   let len = String.length str in
 >   let result = match encrypted with
 >     | None -> String.create len
 >     | Some s -> s
 >   in
 >   (* ... *)
 >   result

> Which gave me more than a 2x speedup while still being able to call a  
> simple:
> let encrypted = encrypt str
> during normal usage

I use this strategy a lot and found that it eventually pays to use
uniform conventions for that: all my functions that can benefit from
having space pre-allocated where to write a result to use ?target
as their very first named optional argument (and also return that
target buffer afterwards).

However, unless I am mistaken, I fear that this also does introduce
some intrinsic/unavoidable inefficiency, as providing a ?target
argument will (presuambly?) require dynamic consing of a <thingy>
option cell - so not a good idea for a very small function that is
called very very often.

There are many many way more advanced tricks one would want to play
with the idea of "allocating buffers at the appropriate time". For
example, if this were LISP, one could often use dynamically scoped (in
the sense of (declare (dynamic-extent buffer-stack))) contextual
variables for great benefit (and these gory details often can also be
hidden quite conveniently under a few (maybe even in-place macrolet)
macros...), but unfortunately, OCaml does not support anything like
that. Of course, re-entrantness of your code may always become an
issue if you move buffers to higher scopes.

One thing OCaml can do better than, say, CMU CL, is to define globally
visible functions that depend on some otherwise inaccessible context,
as in the following example:

let float_factorial =
   let _known_factorials = ref [|1.0;1.0;2.0;6.0;24.0;120.0;720.0|] in
   (fun n ->
     let known_factorials = !_known_factorials in
     let nr_known = Array.length known_factorials in
     if n < nr_known
     then
       known_factorials.(n)
     else
       let new_known_factorials = Array.make (n+1) 0.0 in
       begin
	for i=0 to nr_known-1 do
	  new_known_factorials.(i) <- known_factorials.(i)
	done;
	(let rec fill f_pos pos =
	  if pos > n then ()
	  else
	    let () = new_known_factorials.(pos) <- f_pos in
	    fill (f_pos *. (float_of_int (pos+1))) (pos+1)
	in
	fill (known_factorials.(nr_known-1)*.(float_of_int nr_known)) nr_known);
	_known_factorials := new_known_factorials;
	new_known_factorials.(n)
       end)
;;

A corresponding

(let ((buffer (make-array ...)))
  (defun float-factorial (n)
     ...))

just plainly does not work with CMU CL/SBCL. :-(

Other advanced optimization techniques that can be used for benefit
in very specialized situations include (explicit) continuation coding:
rather than returning a value (e.g. a tuple), you take as an argument
a function to which you then pass on your return value(s). This is quite
useful whenever "execution flow branches out into multiple paths that
have to be taken", and may sometimes (though rarely) also be used for
good as a poor man's VALUES/MULTIPLE-VALUE-BIND substitute.

-- 
best regards,
Thomas Fischbacher
tf@functionality.de


  parent reply	other threads:[~2007-06-27 13:56 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-27 12:14 Jon Harrop
2007-06-27 13:18 ` [Caml-list] " Quôc Peyrot
2007-06-27 13:53   ` Jon Harrop
2007-06-27 14:18     ` Thomas Fischbacher
2007-06-27 15:09     ` Quôc Peyrot
2007-06-27 15:28     ` Mattias Engdegård
2007-06-27 15:38       ` Robert Fischer
2007-06-27 15:48         ` Mattias Engdegård
2007-06-27 16:01           ` Robert Fischer
2007-06-27 16:01           ` Mattias Engdegård
2007-06-27 18:06           ` Jon Harrop
2007-06-27 18:31             ` Brian Hurt
2007-06-27 19:56               ` skaller
2007-06-27 20:17               ` Jonathan Bryant
2007-06-27 22:57               ` Jon Harrop
2007-06-27 16:53     ` Hash-consing (was Re: [Caml-list] The Implicit Accumulator: a design pattern using optional arguments) Daniel Bünzli
2007-06-30  8:19     ` [Caml-list] The Implicit Accumulator: a design pattern using optional arguments Pierre Etchemaïté
2007-06-27 13:55   ` Thomas Fischbacher [this message]
2007-06-27 15:06     ` Quôc Peyrot
2007-06-27 15:53       ` Jon Harrop
2007-06-28 11:01         ` Thomas Fischbacher
2007-06-28 11:32           ` Jon Harrop
2007-06-28 11:42             ` Joel Reymont
2007-06-28 12:08               ` Jon Harrop
2007-06-28 13:10                 ` Quôc Peyrot
2007-06-28 13:35                   ` Thomas Fischbacher
2007-06-28 12:59             ` Thomas Fischbacher
2007-06-28 13:05               ` Jon Harrop
2007-06-28 13:33                 ` Thomas Fischbacher
2007-06-28 14:43                   ` Jon Harrop
2007-06-28 16:01                     ` Thomas Fischbacher
2007-06-28 17:53                       ` Jon Harrop
2007-06-27 16:39       ` Thomas Fischbacher
2007-06-27 19:26         ` Quôc Peyrot
2007-06-28 11:39           ` Thomas Fischbacher
2007-06-28 14:44             ` Jon Harrop
2007-06-28 16:03               ` Thomas Fischbacher
2007-06-28 17:20                 ` Dirk Thierbach
2007-06-28 22:12                   ` Thomas Fischbacher
2007-06-29  1:10                     ` Jon Harrop
2007-06-29 10:55                       ` Thomas Fischbacher
2007-06-29  6:12                     ` Dirk Thierbach
2007-06-27 17:16       ` Book about functional design patterns Gabriel Kerneis
2007-06-27 17:48         ` [Caml-list] " Jon Harrop
2007-06-27 19:33           ` Quôc Peyrot
2007-06-27 19:30         ` Quôc Peyrot
2007-06-27 19:48           ` Brian Hurt
2007-06-27 20:04             ` Quôc Peyrot
2007-06-27 20:35               ` Brian Hurt
2007-06-27 20:55                 ` Quôc Peyrot
2007-06-27 20:58                   ` Pal-Kristian Engstad
2007-06-27 21:18                     ` Quôc Peyrot
2007-06-27 21:18                       ` Pal-Kristian Engstad
2007-06-27 21:34                         ` Quôc Peyrot
2007-06-27 22:13                           ` Pal-Kristian Engstad
2007-06-27 15:18     ` [Caml-list] The Implicit Accumulator: a design pattern using optional arguments Jon Harrop
2007-06-27 16:44       ` Thomas Fischbacher
2007-06-27 18:17         ` Jon Harrop
2007-06-28 11:18           ` Thomas Fischbacher
2007-06-29 13:15     ` Bill Wood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46826C69.5060802@functionality.de \
    --to=tf@functionality.de \
    --cc=caml-list@yquem.inria.fr \
    --cc=chojin@lrde.epita.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).