Version française
Home     About     Download     Resources     Contact us    
Browse thread
Average cost of the OCaml GC
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: ygrek <ygrekheretix@g...>
Subject: Re: [Caml-list] Average cost of the OCaml GC
On Fri, 12 Nov 2010 12:27:40 -0500
Jianzhou Zhao <jianzhou@seas.upenn.edu> wrote:

> Do we still have other methods to debug such problems? Is it possible
> to know when and where GC runs, say, the number of times GC works
> after a particular usr-defined function? If this is possible, I was
> wondering if we can see which function in my code behave wrong.

Below is straghtforward "GC diffing" code which helps me to pinpoint excessive GC 
(like the ExtLib.String.nsplit in example).

$ cat a.ml 

open Printf
open Gc

let bytes_string_f f = (* oh ugly *)
  let a = abs_float f in
  if a < 1024. then sprintf "%dB" (int_of_float f) else
  if a < 1024. *. 1024. then sprintf "%dKB" (int_of_float (f /. 1024.)) else
  if a < 1024. *. 1024. *. 1024. then sprintf "%.1fMB" (f /. 1024. /. 1024.) else
  sprintf "%.1fGB" (f /. 1024. /. 1024. /. 1024.)

let bytes_string x = bytes_string_f (float_of_int x)

let caml_words_f f =
  bytes_string_f (f *. (float_of_int (Sys.word_size / 8)))

let caml_words x = caml_words_f (float_of_int x)

let gc_diff st1 st2 =
  let allocated st = st.minor_words +. st.major_words -. st.promoted_words in
  let a = allocated st2 -. allocated st1 in
  let minor = st2.minor_collections - st1.minor_collections in
  let major = st2.major_collections - st1.major_collections in
  let compact = st2.compactions - st1. compactions in
  let heap = st2.heap_words - st1.heap_words in
  sprintf "allocated %10s, heap %10s, collection %d %d %d" (caml_words_f a) (caml_words heap) compact major minor

let gc_show name f x =
  let st = Gc.quick_stat () in
  Std.finally (fun () -> let st2 = Gc.quick_stat () in 
    eprintf "GC DIFF %s : %s\n" name (gc_diff st st2)) f x

let () =
  let _ = gc_show "split" (ExtLib.String.nsplit (String.make 10000 'a')) "a" in
  gc_show "compact" Gc.compact ()

$ ocamlfind ocamlopt -linkpkg -package extlib a.ml -o a
$ ./a 
GC DIFF split : allocated     48.1MB, heap     48.0MB, collection 0 21 373
GC DIFF compact : allocated       240B, heap    -48.0MB, collection 1 2 0

-- 
 ygrek
 http://ygrek.org.ua