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 _______________________________________________ Caml-list mailing list. Subscription management: http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.inria.fr Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs