perf: reduce allocations in CCSeq.to_array

This commit is contained in:
Simon Cruanes 2022-02-11 21:15:09 -05:00
parent 2a1c7cd8f0
commit 45f567dca1
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6

View file

@ -414,16 +414,17 @@ let of_string s =
let to_array l = let to_array l =
(* We contruct the length and list of seq elements (in reverse) in one pass *) (* We contruct the length and list of seq elements (in reverse) in one pass *)
let len, ls = fold_left (fun (i, acc) x -> (i + 1, x :: acc)) (0, []) l in let len = ref 0 in
let ls = fold_left (fun acc x -> incr len; x :: acc) [] l in
(* The length is used to initialize the array, and then to derive the index for (* The length is used to initialize the array, and then to derive the index for
each item, working back from the last. This lets us only traverse the list each item, working back from the last. This lets us only traverse the list
twice, instead of having to reverse it. *) twice, instead of having to reverse it. *)
match ls with match ls with
| [] -> [||] | [] -> [||]
| init::rest -> | init::rest ->
let a = Array.make len init in let a = Array.make !len init in
(* Subtract 1 for len->index conversion and 1 for the removed [init] *) (* Subtract 1 for len->index conversion and 1 for the removed [init] *)
let idx = len - 2 in let idx = !len - 2 in
ignore (List.fold_left (fun i x -> a.(i) <- x; i - 1) idx rest : int); ignore (List.fold_left (fun i x -> a.(i) <- x; i - 1) idx rest : int);
a a