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

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Florent Monnier <monnier.florent@g...>
Subject: Re: [Caml-list] caml_copy_string
Le lundi 23 août 2010 14:59:19, Stéphane Glondu a écrit :
> Le 23/08/2010 14:09, Florent Monnier a écrit :
> >> Is there a way to get a string from C to OCaml without the
> >> caml_copy_string function, or is there a version that doesn't copy the
> >> string?
> > 
> > an alternative method is to provide a string from ocaml to c then c fills
> > this buffer, then you can save allocations by reusing the same buffer,
> > see: [...]
> 
> You can also wrap your C pointer into bigarrays.

with a ba buffer speed is close than with a string buffer
but with ba allocs it is very slow:

$ ocamlopt -o test.opt bigarray.cmxa main.ml main_stub.c 

$ time ./test.opt 1
44 seconds elapsed

$ time ./test.opt 2
21 seconds elapsed

$ time ./test.opt 3
3 minutes 28 seconds elapsed
(208 seconds elapsed)

$ time ./test.opt 4
25 seconds elapsed

========================

#include <string.h>
#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/fail.h>
#include <caml/bigarray.h>

static const char *str = "the walking camel";
static const int len = 18;

CAMLprim value ml_mystr1(value unit) {
    return caml_copy_string(str);
}
CAMLprim value ml_mystr2(value ml_buf) {
    int buf_len = caml_string_length(ml_buf);
    if (len > buf_len) caml_failwith("buffer overflow");
    memcpy(String_val(ml_buf), str, len);
    return Val_int(len);
}

CAMLprim value ml_mysba1(value unit) {
    long dims[3];
    dims[0] = len;
    return caml_ba_alloc(CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 1, NULL, dims);
}
CAMLprim value ml_mysba2(value ba) {
    unsigned char *ptr;
    int ba_size = caml_ba_byte_size(Caml_ba_array_val(ba));
    if (len > ba_size) caml_failwith("buffer overflow");
    ptr = Caml_ba_data_val(ba);
    memcpy(ptr, str, len);
    return Val_int(len);
}

========================

external mystr1: unit -> string = "ml_mystr1"
external mystr2: string -> int = "ml_mystr2" "noalloc"

type ba_string =
  (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t

external mysba1: unit -> ba_string = "ml_mysba1"
external mysba2: ba_string -> int = "ml_mysba2" "noalloc"

let n = 1_000_000_000

let test1() =
  for i = 1 to n do
    let _ = mystr1 () in ()
  done

let test2() =
  let buf = String.create 100 in
  for i = 1 to n do
    let _ = mystr2 buf in ()
  done

let test3() =
  for i = 1 to n do
    let _ = mysba1 () in ()
  done

let test4() =
  let bstr = Bigarray.Array1.create Bigarray.char Bigarray.c_layout 100 in
  for i = 1 to n do
    let _ = mysba2 bstr in ()
  done

let () =
  match Sys.argv.(1) with
  | "1" -> test1()
  | "2" -> test2()
  | "3" -> test3()
  | "4" -> test4()
  | _ -> assert false

========================

-- 
Regards
Florent