String.concat

Florent Monnier <[email protected]> Thu, 6 May 2010 00:30:21 +0200
Newsgroups gmane.comp.lang.ocaml.lib.devel
Message-ID <[email protected]>
Hi,
It's possible to enhance String.concat a little bit.
(Find the patch joined to this email.)
Indeed in the std-lib there are extraneous calls to String.length.
Here is a short bench that shows the difference:

let _concat sep l =
  let len_sep = String.length sep in
  match l with
    [] -> ""
  | hd :: tl ->
      let len_hd = String.length hd in
      let num = ref 0 and len = ref 0 in
      List.iter (fun s -> incr num; len := !len + String.length s) l;
      let r = String.create (!len + len_sep * (!num - 1)) in
      String.unsafe_blit hd 0 r 0 len_hd;
      let pos = ref len_hd in
      List.iter
        (fun s ->
          let len_s = String.length s in
          String.unsafe_blit sep 0 r !pos len_sep;
          pos := !pos + len_sep;
          String.unsafe_blit s 0 r !pos len_s;
          pos := !pos + len_s)
        tl;
      r

let time_it lbl n f v =
  let t1 = Unix.gettimeofday() in
  for i = 1 to n do
    let _ = f v in ()
  done;
  let t2 = Unix.gettimeofday() in
  Printf.printf " %s %f sec.\n" lbl (t2 -. t1);
;;

let () =
  let li = ["The"; "quick"; "brown"; "fox"; "jumps"; "over"; "the"; "lazy"; 
"dog"] in
  let n = 1_000_000 in
  time_it "std   :" n (String.concat " ") li;
  time_it "custom:" n (_concat " ") li;
;;
_____________________________

here is an example output:

 std   : 0.462470 sec.
 custom: 0.410706 sec.

================================
In the std-lib concat is written like this:

let concat_ sep l =
  match l with
    [] -> ""
  | hd :: tl ->
      let num = ref 0 and len = ref 0 in
      List.iter (fun s -> incr num; len := !len + length s) l;
      let r = create (!len + length sep * (!num - 1)) in
      unsafe_blit hd 0 r 0 (length hd);
      let pos = ref(length hd) in
      List.iter
        (fun s ->
          unsafe_blit sep 0 r !pos (length sep);
          pos := !pos + length sep;
          unsafe_blit s 0 r !pos (length s);
          pos := !pos + length s)
        tl;
      r
================================

-- 
Regards

------------------------------------------------------------------------------

_______________________________________________
ocaml-lib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ocaml-lib-devel
extlib-1.5.1-extString.ml.patch (text/x-patch, 865 B)
--- extlib-1.5.1/extString.ml.orig	2010-05-06 00:17:33.000000000 +0200
+++ extlib-1.5.1/extString.ml	2010-05-06 00:19:10.000000000 +0200
@@ -104,6 +104,27 @@
 		nsplit str sep
 	)
 
+let concat sep l =
+  let len_sep = length sep in
+  match l with
+    [] -> ""
+  | hd :: tl ->
+      let len_hd = length hd in
+      let num = ref 0 and len = ref 0 in
+      List.iter (fun s -> incr num; len := !len + length s) l;
+      let r = create (!len + len_sep * (!num - 1)) in
+      unsafe_blit hd 0 r 0 len_hd;
+      let pos = ref len_hd in
+      List.iter
+        (fun s ->
+          let len_s = length s in
+          unsafe_blit sep 0 r !pos len_sep;
+          pos := !pos + len_sep;
+          unsafe_blit s 0 r !pos len_s;
+          pos := !pos + len_s)
+        tl;
+      r
+
 let join = concat
 
 let slice ?(first=0) ?(last=Sys.max_string_length) s =