Re: [Caml-list] Non-blocking IO interface design

2012-04-09 Thread Anil Madhavapeddy
On 8 Apr 2012, at 21:37, Daniel Bünzli wrote:
 
 I think that the first five points are mostly met and the
 cps transformation of blocking into non-blocking is relatively
 straightforward and remains readable in my opinion. Regarding the 6th
 point, using the included `setrip.native` program on 32 Mo of randomly
 generated s-expressions seem to indicate that:
 
  The non-blocking decoder can be at least 1.35 slower than blocking
  The non-blocking encoder can be at least 1.1 slower than blocking
 
 Now I don't think these bad numbers should be taken to dismiss the
 approach since in the context of a larger reactive program a blocking
 codec may actually incur performance and scability issues that cannot
 be shown by this example program.

To track this down (as I'm learning about ocaml profiling at the moment),
I firstly ran the blocking and non-blocking decoder through ocamlcp to check 
call counts, and:

(non-blocking)
let decode_nb_unix usize fd =   
  
  (* 2 *) let rec loop d fd buf = (* 18039140 *) match Se.Nb.decode d with  
  
  | `Lexeme l - (* 18035048 *) loop d fd buf
  | `End - (* 2 *) `Ok  
  | `Error - (* 0 *) `Error
  
  | `Await - 
  (* 4090 *) let rc = unix_read fd buf 0 (String.length buf) in 
  
  Se.Nb.decode_src d buf 0 rc; loop d fd buf
  
  in
  loop (Se.Nb.decoder `Manual) fd (String.create usize) 
  

(blocking)
let decode_b src =
  (* 1 *) let rec loop d = (* 9017525 *) match Se.B.decode d with
  | `Lexeme l - (* 9017524 *) loop d
  | `End - (* 1 *) `Ok
  | `Error - (* 0 *) `Error
  in
  loop (Se.B.decoder src)

The I/O loop is being called twice for the non-blocking version, as it receives 
the `Await signal, does the Unix syscall, and then jumps into decode_src. 
Presumably
a full non-blocking version would have to register with a select handler if it
gets an EAGAIN at this point,

In terms of the number of system calls, the non-blocking one is more efficient,
as it uses a 16KB buffer versus the 4K reads done by the blocking version. 

$ strace ./setrip.native -dec -unix   foo.sexp  21 | wc -l
2107
$ strace ./setrip.native -dec -unix -b   foo.sexp  21 | wc -l
8238

Running 'perf stat' on the decoder on Linux shows that the non-blocking version
is spending more CPU time doing something:

$ perf stat --log-fd 1 ./setrip.native -dec -unix -b   foo.sexp  
 Performance counter stats for './setrip.native -dec -unix -b':

   1095.337180 task-clock#1.000 CPUs utilized  
 1 context-switches  #0.000 M/sec  
 0 CPU-migrations#0.000 M/sec  
   800 page-faults   #0.001 M/sec  

$ perf stat --log-fd 1 ./setrip.native -dec -unix  foo.sexp  
 Performance counter stats for './setrip.native -dec -unix':

   1339.360940 task-clock#1.000 CPUs utilized  
 2 context-switches  #0.000 M/sec  
 0 CPU-migrations#0.000 M/sec  
   823 page-faults   #0.001 M/sec  


Setting the GC to verbose shows that the non-blocking one is doing way more
heap allocations than the blocking version (14 heap checks, versus 3). So this
quick'n'dirty function is stuck in the source to bracket hot-looking calls and
see how many minor heap allocations are taking place.

let gcbracket fn a =
   
  let open Gc in
  compact ();
  let s1 = stat () in
  let r = fn a in
  let s2 = stat () in
  let r = fn a in
  Printf.eprintf gc: %.0f [%.0f %.0f %.0f / %.0f %0.f %0.f]\n%!
(s2.minor_words -. s1.minor_words) s1.minor_words s1.promoted_words
s1.major_words s2.minor_words s2.promoted_words s2.major_words;
  r

Looking at the two decoders in src/se.ml, it looks like the non-blocking one
allocates closures on every loop, which the blocking one doesn't. This is so it
can store the continuation in d.k for the next loop. So putting gcbracket around
the two decode calls confirms this. Switching to bytecode so we have accurate 
minor
heap states, we have:

For the blocking one:
gc: 31 [1450548 0 44224 / 1450579 0 44224]
gc: 31 [1451229 0 44255 / 1451260 0 44255]
gc: 31 [1452506 0 44278 / 1452537 0 44278]
gc: 31 [1453187 0 44309 / 1453218 0 44309]

The important number is the first one (difference in minor heap size before and
after the function, which is solidly 31.

With the non-blocking one, more words are allocated in the minor heap:
gc: 67 [5368 0 4684 / 5435 0 4684]
gc: 42 [6096 0 4723 / 6138 

Re: [Caml-list] Re: oasis packaging questions

2012-03-09 Thread Anil Madhavapeddy
On 8 Mar 2012, at 22:26, Sylvain Le Gall wrote:
 
 2012/3/8 Adrien camarade...@gmail.com:
 Hi,
 
 On 08/03/2012, Sylvain Le Gall sylv...@le-gall.net wrote:
 Hi,
 
 2012/3/8 Daniel Bünzli daniel.buen...@erratique.ch:
 Le jeudi, 8 mars 2012 ŕ 09:31, Sylvain Le Gall a écrit :
 setup.ml will be enough for me ;-) But I am biased.
 
 For distribution, I'm fine with that aswell. For developement setup.ml
 takes too much time to invoke (adds an overhead of 0.5s on my system).
 
 
 That the parsing time because the file is big. I know this issue and
 will try to improve that in the future. I think a 50% down size is
 possible, that will bring this time to 250ms. Although, I don't think
 that even for development env a 500ms delay is that big... I doubt to
 be able to reduce to ~0s.
 
 For my own stuff, I've been using a Makefile which includes a rule to
 (re)compile setup.ml into an executable with ocamlc.opt (compiling
 with ocamlopt was too slow). My usual development machine isn't
 terribly fast and this has helped a lot.
 
 I think there was a mention of an issue though but it can help a lot.
 
 Make sense. So super quick hack!
 
 Add at the beginning of setup.ml:

A Makefile works just fine (and making the autogenerated code less complex
rather than more would be better).

This is the template Makefile I use:
https://github.com/avsm/ocaml-github/blob/master/Makefile

-anil

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



[Caml-list] working %.pp.ml target with ocamfind/ocamlbuild

2011-12-30 Thread Anil Madhavapeddy
There's a very useful %.pp.ml target in OCamlbuild that runs the source through 
camlp4 and outputs the result.  This doesn't work when ocamlfind is used, as it 
includes the -pp flags within the ocamlfind invocation.

I took a look at adding support for this into ocamlbuild (when -use-ocamlfind 
is specified), but I couldn't spot any way to get ocamlfind to output the 
syntax options.

I just wanted to check that this is all in fact true, since it requires 
patching ocamlbuild, findlib, and oasis to make it work. Does everyone else 
manually run the camlp4o command when using syntax extensions like type-conv or 
pa_lwt?

-anil

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Re: how could the community help with Oasis-DB; towards a CPAN for OCaml?

2011-12-18 Thread Anil Madhavapeddy
On 18 Dec 2011, at 20:01, Benedikt Meurer wrote:

 Am 18.12.2011 um 20:46 schrieb Ashish Agarwal agarwal1...@gmail.com:
 
 On Sun, Dec 18, 2011 at 4:35 AM, Benedikt Meurer 
 benedikt.meu...@googlemail.com wrote:
  
 the OASIS port is named caml-oasis.
 
 Please try to transition to the consistent name OCaml, a decision made at 
 the 2011 OCaml Users Meeting. Using it in lower case is okay in certain 
 contexts such as a package name, so here I would recommend ocaml-oasis.
 
 This is the prefix used within MacPorts to identify OCaml packages. I don't 
 know why it isn't ocaml.

It's just historical. I imported a bunch of OCaml packages into Macports a few 
years ago and preserved the prefix since it wasn't really worth the trouble to 
rename so many ports.

I've actually given up on MacPorts and switched to Homebrew recently. They 
don't like importing libraries in Homebrew and defer that to the 
language-specific package manager.  I'm hoping that odb will be sufficient to 
act as the lightweight library installer to complement Homebrew.

The only annoying thing about installing OCaml from source these days is the 
'compiler-libs' convention that most packages seem to do, but isn't really 
written down anywhere. Is there a Mantis bug about this one (I couldn't find 
one)? It's really helpful to get the Lwt toplevel working and isn't very 
obvious where those files come from without diving into the Debian packaging.

I've got a small pull request to add it to the Homebrew package at any rate. 
Comment on it to give it some life and it might even get merged... 
https://github.com/mxcl/homebrew/pull/9002

-anil
-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Storing ocaml values outside ocaml's heap

2011-12-08 Thread Anil Madhavapeddy
I think Ancient is exactly what you're looking for.

Just disable swap (which you should do anyway on a big modern server), and it 
will let you keep in-memory, out-of-heap OCaml values that don't get scanned by 
the GC.

Anil

On 8 Dec 2011, at 08:19, William Le Ferrand wrote:

 hi Stephane
 
 Yes, but it's not exactly what we're looking for : we plan to access the data 
 at a (very) high rate, so swapping/unswapping would probably kill the 
 performance .. 
 
 
 On Wed, Dec 7, 2011 at 10:04 PM, Stéphane Glondu st...@glondu.net wrote:
 Le 08/12/2011 05:35, William Le Ferrand a écrit :
  We are building a cache in ocaml and we're wondering if it would make
  sense to store ocaml values outside the reach of the gc. (gc on a 20GB
  cache hangs the process for a second or so).
 
 Have you heard of the ancient [1] library?
 
 [1] http://git.annexia.org/?p=ocaml-ancient.git;a=summary
 
 
 Cheers,
 
 --
 Stéphane
 
 
 
 
 -- 
 William Le Ferrand
 
 Mobile : (+1) (415) 683-1484
 Web : http://williamleferrand.github.com/
 


-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] Async, a monadic concurrency library

2011-10-26 Thread Anil Madhavapeddy
On Wed, Oct 26, 2011 at 12:06:43PM +0100, Mark Shinwell wrote:
 On Wed, Oct 26, 2011 at 07:03:43AM -0400, Yaron Minsky wrote:
  I'll leave Stephen to answer that one.  I'm just the front-man here.
  Stephen's the one who did all the actual work on Async...
 
 Actually, I think I'm probably responsible for this one.  I believe the
 problem was a kernel bug/feature which caused an internal error code to
 be exposed to userspace instead of EINTR.

Have you ever seen this outside of using ptrace/strace? If it actually
leaks to userspace when not used on inside those, that would break a lot
of other applications.

Anyhow, directly checking the number is bad for portability reasons as the
ERESTARTNOHAND is a Linux-ism. I'm taking a shot at porting Core/Async to
OpenBSD at the moment, so will patch out that check in our local changes).

-- 
Anil Madhavapeddy http://anil.recoil.org

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] Lwt and exceptions

2011-09-15 Thread Anil Madhavapeddy
On 15 Sep 2011, at 11:04, Mehdi Dogguy wrote:

 On 13/09/2011 20:37, ri...@happyleptic.org wrote:
 The Lwt doc states that you should not use raise when using Lwt but 
 use Lwt.fail instead.
 
 So, is it still OK to call functions (for instance from the stdlib) 
 that may raise an exception, provided we catch it soon enough ? And by 
 soon enough I mean: before an Lwt call that could schedule another 
 thread.
 
 
 I guess, not (and it has been answered already). In fact, I was wondering
 if Lwt's authors would be against adding a function like:
 
   let wrap f x = try Lwt.return (f x) with e - Lwt.fail e
 
 It is stupid, trivial, etc… but looks what we need most of the time, no?
 Instead of doing it in our own code, it could land in Lwt directly.
 But, if it gets integrated into Lwt proper, users should be warned about
 its behaviour. (especially with impure functions).

The try_lwt construct (in pa_lwt) or try_bind already converts normal 
exceptions into Lwt ones:

  try_lwt
raise (Failure )
  with Failure _ -
print_endline Fail; Lwt.return ()

...will print Fail.

You just need to careful about raising exceptions across yield points when a 
try_lwt isn't present. The slightly painful thing about converting existing 
code to Lwt is that any function that raises an exception will gain the Lwt 
type if you convert it to use try_lwt/catch, even if the rest of the code 
doesn't otherwise block.

Anil



-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



[Caml-list] output-obj rule in ocamlbuild

2011-08-25 Thread Anil Madhavapeddy
Is there a built-in rule in ocamlbuild to generate the -output-obj output 
instead of a direct link?

I note there are these built-in tags in the ocamlbuild source:

ocaml_specific.ml:flag [ocaml; link; native; output_obj] 
(A-output-obj);;
ocaml_specific.ml:flag [ocaml; link; byte; output_obj] 
(A-output-obj);;

...but I can't find a built-in target that uses these tags. Is a custom rule in 
myocamlbuild.ml needed here, or should I do something in my _tags file?

cheers,
Anil

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs