diff options
author | Stephane Glondu <steph@glondu.net> | 2020-08-25 07:00:43 +0200 |
---|---|---|
committer | Stephane Glondu <steph@glondu.net> | 2020-08-25 07:00:43 +0200 |
commit | b77c4da1a30c0db71de9bf48c5b85bc47f9c5210 (patch) | |
tree | 12f3512802b4e7042fc175c00fcc5d204a506bc0 | |
parent | 7db70fe2b1be8b026b29e14463a63ad914a8cc1f (diff) |
New upstream version 1.4
-rw-r--r-- | META | 4 | ||||
-rw-r--r-- | _oasis | 21 | ||||
-rw-r--r-- | _tags | 24 | ||||
-rw-r--r-- | benchmark.ml | 261 | ||||
-rw-r--r-- | benchmark.mli | 136 | ||||
-rw-r--r-- | myocamlbuild.ml | 88 | ||||
-rw-r--r-- | setup.ml | 229 | ||||
-rw-r--r-- | tests/tree.ml | 22 |
8 files changed, 647 insertions, 138 deletions
@@ -1,6 +1,6 @@ # OASIS_START -# DO NOT EDIT (digest: 8d589cce128284ea37136fa3315db0ab) -version = "1.3.1" +# DO NOT EDIT (digest: d46739ab84ae5c81a14032b8a0cb2453) +version = "1.4" description = "Benchmark running times of code." requires = "unix" archive(byte) = "benchmark.cma" @@ -1,15 +1,17 @@ # -*-conf-*- -OASISFormat: 0.3 +OASISFormat: 0.4 Name: benchmark -Version: 1.3.1 +Version: 1.4 Synopsis: Benchmark running times of code. Authors: Christophe Troestler <Christophe.Troestler@umons.ac.be> +Maintainers: Christophe Troestler <Christophe.Troestler@umons.ac.be> License: LGPL-3.0 with OCaml linking exception Description: This module provides a set of tools to measure the running times of your functions and to easily compare the results. A statistical test is used to determine whether the results truly differ. Plugins: META (0.2) Homepage: http://ocaml-benchmark.forge.ocamlcore.org/ +OCamlVersion: >= 3.12.0 Flag examples Description: Whether to compile the examples. @@ -130,7 +132,16 @@ Executable long_run CompiledObject: best Install: false +Executable tree + Build$: flag(tests) + Path: tests + MainIs: tree.ml + BuildTools: ocamlbuild + BuildDepends: benchmark + CompiledObject: best + Install: false + SourceRepository trunk - Type: svn - Location: svn://scm.ocamlcore.org/svn/ocaml-benchmark/trunk - Browser: https://forge.ocamlcore.org/scm/browser.php?group_id=197 + Type: git + Location: https://github.com/Chris00/ocaml-benchmark.git + Browser: https://github.com/Chris00/ocaml-benchmark @@ -1,8 +1,9 @@ # OASIS_START -# DO NOT EDIT (digest: 17f396b5386ca66b9662796db29eb18c) +# DO NOT EDIT (digest: 23c578b63f53f29d8fe090eaed8ca940) # Ignore VCS directories, you can use the same kind of rule outside # OASIS_START/STOP if you want to exclude directories that contains # useless stuff for the build process +true: annot, bin_annot <**/.svn>: -traverse <**/.svn>: not_hygienic ".bzr": -traverse @@ -15,7 +16,7 @@ "_darcs": not_hygienic # Library benchmark "benchmark.cmxs": use_benchmark -<*.ml{,i}>: pkg_unix +<*.ml{,i,y}>: pkg_unix # Executable ar_ba <examples/ar_ba.{native,byte}>: pkg_bigarray <examples/ar_ba.{native,byte}>: pkg_unix @@ -45,22 +46,25 @@ <examples/regexps.{native,byte}>: pkg_str <examples/regexps.{native,byte}>: pkg_unix <examples/regexps.{native,byte}>: use_benchmark -<examples/*.ml{,i}>: pkg_pcre -<examples/*.ml{,i}>: pkg_str +<examples/*.ml{,i,y}>: pkg_pcre +<examples/*.ml{,i,y}>: pkg_str # Executable try_if <examples/try_if.{native,byte}>: pkg_bigarray <examples/try_if.{native,byte}>: pkg_unix <examples/try_if.{native,byte}>: use_benchmark -<examples/*.ml{,i}>: pkg_bigarray +<examples/*.ml{,i,y}>: pkg_bigarray # Executable func_record <examples/func_record.{native,byte}>: pkg_unix <examples/func_record.{native,byte}>: use_benchmark -<examples/*.ml{,i}>: pkg_unix -<examples/*.ml{,i}>: use_benchmark +<examples/*.ml{,i,y}>: pkg_unix +<examples/*.ml{,i,y}>: use_benchmark # Executable long_run <tests/long_run.{native,byte}>: pkg_unix <tests/long_run.{native,byte}>: use_benchmark -<tests/*.ml{,i}>: pkg_unix -<tests/*.ml{,i}>: use_benchmark +# Executable tree +<tests/tree.{native,byte}>: pkg_unix +<tests/tree.{native,byte}>: use_benchmark +<tests/*.ml{,i,y}>: pkg_unix +<tests/*.ml{,i,y}>: use_benchmark # OASIS_STOP -true: strict_formats +true: strict_formats, safe_string diff --git a/benchmark.ml b/benchmark.ml index 46fb9bc..c96caf2 100644 --- a/benchmark.ml +++ b/benchmark.ml @@ -305,7 +305,7 @@ let make_printer nspace = let null_printer = { print_indent = (fun _ -> ()); print = (fun _ -> ()) } -(* Generic interface for performing measurments on a list of functions *) +(* Generic interface for performing measurements on a list of functions *) let testN ~test default_f_name ?min_count ?min_cpu ~style ?fwidth ?fdigits ~repeat funs = let length_name = @@ -614,3 +614,262 @@ let tabulate ?(no_parent=false) ?(confidence=0.95) results = row_formatter top_row; List.iter row_formatter rows; flush stdout + +(** {2 Bench Tree} *) + +module Tree = struct + (** {2 Path} *) + + type path = string list + + let print_path_element fmt p = + Format.pp_print_char fmt '.'; + Format.pp_print_cut fmt (); + Format.pp_print_string fmt p + + let print_path fmt path = + Format.fprintf fmt "@[<2>"; + (match path with + | [] -> () + | [p] -> Format.pp_print_string fmt p + | p :: tl -> Format.pp_print_string fmt p; + List.iter (print_path_element fmt) tl); + Format.fprintf fmt "@]" + + (* Split the string along "." characters. Specification: + assert (parse_path "foo.bar" = ["foo";"bar"]); + assert (parse_path "foo" = ["foo"]); + assert (parse_path "" = [""]) + *) + let rev_parse_path check_name s = + let l = ref [] in + let i0 = ref 0 in + for i = 0 to String.length s - 1 do + if String.unsafe_get s i = '.' then ( + let name = String.sub s !i0 (i - !i0) in + check_name name; + l := name :: !l; + i0 := i + 1; + ) + done; + let name = if !i0 = 0 then s + else String.sub s !i0 (String.length s - !i0) in + check_name name; + name :: !l + + let check_reserved name = + if name = "*" then invalid_arg "Name \"*\" is reserved for wildcard" + + let check_nothing _ = () + + let parse_path s = + List.rev(rev_parse_path check_nothing s) + + + (** {2 Bench Tree} *) + + module SMap = Map.Make(String) + + (* A collection of benchmarks with fast concatenation. *) + type benches = Single of samples Lazy.t + | Pair of benches * benches + + let merge_benches_opt b1 b2 = match b1, b2 with + | None, b | b, None -> b + | Some b1, Some b2 -> Some(Pair(b1, b2)) + + let rec number_of_benches = function + | Single _ -> 1 + | Pair(b1, b2) -> number_of_benches b1 + number_of_benches b2 + + let rec benches_iter benches ~f = match benches with + | Single b -> f b + | Pair(b1, b2) -> benches_iter b1 ~f; benches_iter b2 ~f + + type t = Tree of benches option * t SMap.t + (* benches at that level + named sublevels. The name "" is + understood as "at this level" and so will not be present in the + map. *) + + let empty = Tree(None, SMap.empty) + + let is_empty (Tree(b, m)) = + b = None && SMap.is_empty m + + let rec merge (Tree(b1, m1)) (Tree(b2, m2)) : t = + let b = merge_benches_opt b1 b2 in + let m = SMap.merge merge_opt m1 m2 in + Tree(b, m) + and merge_opt _ o1 o2 = match o1, o2 with + | None, None -> None + | Some o, None + | None, Some o -> Some o + | Some o1, Some o2 -> Some (merge o1 o2) + + let concat l = List.fold_left merge empty l + + let check_allowed_name n = + if n = "*" then invalid_arg "Name \"*\" is reserved for wildcard"; + for i = 0 to String.length n - 1 do + if String.unsafe_get n i = '.' then + invalid_arg "Names cannot contain dots" + done + + let of_bench bench = Tree(Some(Single bench), SMap.empty) + + let name_nonempty t n = Tree(None, SMap.singleton n t) + + let name t n = + (* Assume the name [n] is valid *) + if n = "" then t else name_nonempty t n + + (* prefix a tree with a path. Now the whole tree is only reachable + from this given path *) + let prefix path t = + List.fold_right (fun n t -> check_reserved n; name t n) path t + + let ( @>> ) n t = + let path = rev_parse_path check_reserved n in + List.fold_left name t path + + let ( @> ) name bench = name @>> (of_bench bench) + + let (@>>>) n l = n @>> (concat l) + + let with_int f = function + | [] -> empty + | l -> + let g i = Tree(None, SMap.singleton (string_of_int i) (f i)) in + concat (List.map g l) + + (* print the structure of the tree, to show the user possible paths *) + let rec print_tree_map fmt m = + SMap.iter (print_tree_path fmt) m + and print_tree_path fmt name (Tree(b, m)) = + (match b with + | None -> Format.fprintf fmt "@\n@[<2>- %s" name + | Some b -> + let n = number_of_benches b in + Format.fprintf fmt "@\n@[<2>- %s: %i benchmark%s" + name n (if n > 1 then "s" else "")); + print_tree_map fmt m; + Format.fprintf fmt "@]" + + let print fmt (Tree(b, m)) = + (match b with + | None -> Format.fprintf fmt "No benchmark at root" + | Some b -> + let n = number_of_benches b in + Format.fprintf fmt "%i benchmark%s at root" + n (if n > 1 then "s" else "")); + print_tree_map fmt m + + (** {2 Selecting a subtree} *) + + let rec filter path (Tree(b,m) as t) = match path with + | [] -> t + | [""] -> (* Only return the benches at this level (no sub-levels) *) + Tree(b, SMap.empty) + | "" :: tl -> (* skip empty component NOT at the end, skip *) + filter tl t + | "*" :: tl -> + (* wildcard pattern, select all subtrees *) + let map_filter name t m = + let t = filter tl t in + (* Keep it only if not empty. *) + if is_empty t then m else SMap.add name t m in + Tree(b, SMap.fold map_filter m SMap.empty) + | p0 :: tl -> + match (try Some(SMap.find p0 m) with Not_found -> None) with + | None -> empty + | Some t -> let t = filter tl t in + (* propagate up the emptiness *) + if is_empty t then empty else name_nonempty t p0 + + (** {2 Run} *) + + let print_sep fmt = + Format.pp_print_string fmt "***********************************\ + ***********************************"; + Format.pp_print_newline fmt () + + let run_bench_path fmt is_previous_output rev_path = function + | None -> is_previous_output + | Some b -> + if is_previous_output then print_sep fmt; + Format.fprintf fmt "*** Run benchmarks for path \"%a\"@\n@." + print_path (List.rev rev_path); + benches_iter b ~f:(fun b -> tabulate (Lazy.force b)); + true + + let rec run_all fmt is_previous_output rev_path (Tree(b, m)) = + let is_previous_output = + run_bench_path fmt is_previous_output rev_path b in + SMap.fold (fun name t is_out -> run_all fmt is_out (name :: rev_path) t) + m is_previous_output + + let run_1path fmt t is_previous_output path = + (* Filtering the tree keep its full paths so we initialize + [rev_path] to [[]]. *) + run_all fmt is_previous_output [] (filter path t) + + let run_paths fmt ~paths t = + let is_out = List.fold_left (run_1path fmt t) false paths in + if not is_out then + match paths with + | [] -> Format.fprintf fmt "No benchmark to run.@\n@." + | p0 :: tl -> + Format.fprintf fmt "No benchmark to run for paths "; + print_path fmt p0; + List.iter (fun p -> print_path fmt p; + Format.pp_print_string fmt ", ") tl; + Format.fprintf fmt ".@\n@." + + type arg_state = { mutable paths : path list; + mutable print_tree : bool; + } + let arg () = + let st = { paths = []; print_tree = false } in + let add_path s = st.paths <- parse_path s :: st.paths in + let options = + [ "--path", Arg.String add_path, " only apply to subpath" + ; "-p", Arg.String add_path, " short option for --path" + ; "--tree", Arg.Unit (fun () -> st.print_tree <- true), " print the tree" + ] in + st, options + + let run ?arg ?(paths=[]) ?(out=Format.std_formatter) t = + match arg with + | None -> run_paths out ~paths t + | Some st -> + if st.print_tree then + Format.fprintf out "@[%a@]@." print t + else + run_paths out ~paths:(paths @ List.rev st.paths) t + + (** {2 Global Registration} *) + + (* the global tree of benchmarks *) + let tree = ref empty + + let global () = !tree + + let register new_t = + tree := merge !tree new_t + + let run_global ?(argv=Sys.argv) ?(out=Format.std_formatter) () = + let st, specs = arg () in + let no_anon _ = raise(Arg.Bad "No anonymous arguments allowed") in + let pgm = try Filename.basename Sys.argv.(0) + with _ -> "run benchmark" in + let usage = pgm ^ " [options]" in + try + Arg.parse_argv argv specs no_anon usage; + run ~arg:st ~out !tree + with Arg.Bad msg -> + Format.fprintf out "%s@." msg +end + +(* Local Variables: *) +(* compile-command: "make -k" *) +(* End: *) diff --git a/benchmark.mli b/benchmark.mli index 514ea20..c55e630 100644 --- a/benchmark.mli +++ b/benchmark.mli @@ -228,3 +228,139 @@ val tabulate : ?no_parent:bool -> ?confidence:float -> samples -> unit @param confidence is used to determine the confidence interval for the Student's test. (default: [0.95]). *) + + +(** {2 Benchmark Tree} + + Naming benchmarks within a hierarchy that allows to run them all, + or filter them so that only a subset is run. *) + +module Tree : sig + type t + (** A (possibly empty) tree of benchmarks. Individual benchmarks + (i.e., calls to {!throughputN}, {!latencyN}, etc. wrapped with + {!(>:)}) can appear at any node of the tree. The edges are + annotated with strings, and paths (see {!path}) are used to + select subtrees. *) + + val ( @> ) : string -> samples Lazy.t -> t + (** [name @> bench] returns a (named) node of the benchmark tree. + If evaluated, it simply returns samples (for instance using + {!throughputN}). If the name contains dots, it is interpreted + as a path. For examle ["a.b" @> bench] is equivalent to ["a" @>> + "b" @> bench]. + + Example (the lazy thunk is used to hide initialization code): + + {[ + Benchmark.Tree.( + "sort" >: lazy + (let a = Array.init 1_000_000 (fun i -> i) in + Benchmark.throughput1 18 (Array.sort compare) a + ) + ) ;; + ]} *) + + val ( @>> ) : string -> t -> t + (** [name >:: tree] makes [tree] accessible through the given + [name], i.e., prefix all paths in the tree by [name]. It has no + effect if [name = ""]. If the name contains dots, it is + interpreted as a path. For instance ["n1.n2" @>> tree] is + equivalent to ["n1" @>> "n2" @>> tree] and adds the path + [[n1;n2]] as a prefix to the tree. + + @raise Invalid_argument is the name is invalid. At least names + corresponding to OCaml identifiers are valid. *) + + val concat : t list -> t + (** Merge the given trees (recursively). Merging proceeds by taking the union + of all path heads in the list, and, for each such string [x], + merging recursively all subtrees reachable under [x]. + + For instance merging the trees [a.{b, c}], [a.b.d] and [{a.d, foo}] + will give the tree [{a.(b, b.d, c, d}, d}]. *) + + val ( @>>> ) : string -> t list -> t + (** [name @>>> l] is equivalent to [name >:: concat l]. It names a list of + trees, and is useful to build lists of benchmarks related to some + common topic. If the name contains dots, it is interpreted + as a path. + + @raise Invalid_argument is the name is invalid. At least names + corresponding to OCaml identifiers are valid. *) + + val with_int : (int -> t) -> int list -> t + (** [with_int f l] parametrize trees with several integer values + (e.g. a size). The tree [f i] is prefixed with the label [i]. *) + + val print : Format.formatter -> t -> unit + (** Print the tree of benchmarks (its structure) on the given formatter. + Useful in combination with the [path] argument of {!run} *) + + (** {2 Path} *) + + type path = string list + (** A path in a tree, pointing at a subtree. *) + + val print_path : Format.formatter -> path -> unit + + val parse_path : string -> path + (** Split a string into a path at the "." separators. + Example: [parse_path "a.b.c"] returns [["a"; "b"; "c"]]. *) + + val prefix : path -> t -> t + (** Add the path as a prefix to the tree, similar to repeated + calls to [>::]. *) + + val filter : path -> t -> t + (** [filter p t] return the tree obtained by keeping all the paths + in [t] that match the path [p]. + Empty components [""] in the middle of the path are ignored. + Empty components [""] at the end of the path return only the + benchmarks at that level (i.e., one discards the benchmarks + pointed by paths of which [p] is a strict prefix). + The special path component ["*"] selects all subtrees at that + level (it acts as a wildcard). *) + + + (** {2 Running} *) + + type arg_state + + val arg : unit -> arg_state * (Arg.key * Arg.spec * Arg.doc) list + (** [arg ()] returns [(arg, specs)] where [arg] is a state coming + from parsing the command line using [specs]. The options are: + - "--path" or "-p" to add a sub-tree of benchmarks + - "--tree" to print the tree of benchmarks. + Note that the default state runs all benchmarks. You need to + use something like [Arg.parse (specs @ more_specs) ...] to make + the above arguments available to the program user. *) + + val run : ?arg: arg_state -> ?paths: path list -> ?out: Format.formatter -> + t -> unit + (** [run t] runs all benchmarks of [t] and print the results to [fmt]. + @param paths if provided, only the sub-trees corresponding to + these path is executed. Default: execute everything. + @param out The formatter on which to print the output. + Default: [Format.std_formatter]. + @param arg use the result of the command line parsing to direct + the run. Default: run all paths in [path] *) + + + (** {2 Global Registration} *) + + val global : unit -> t + (** Global tree, built from calls to {!register}. It is useful + to centralize all benchmarks at one place to, then, run them all *) + + val register : t -> unit + (** Register a benchmark to the global registry of benchmarks. *) + + val run_global : + ?argv:string array -> + ?out:Format.formatter -> + unit -> unit + (** Same as {!run} on the global tree of benchmarks and parsing the + command line arguments from [argv] (which is [Sys.argv] by + default). *) +end diff --git a/myocamlbuild.ml b/myocamlbuild.ml index 4420e8e..78b2a6d 100644 --- a/myocamlbuild.ml +++ b/myocamlbuild.ml @@ -1,5 +1,5 @@ (* OASIS_START *) -(* DO NOT EDIT (digest: 9eb145f6e2b004ab61babdd6aa609803) *) +(* DO NOT EDIT (digest: da78aa0b7ff42be1e339410cde8aeb5c) *) module OASISGettext = struct (* # 22 "src/oasis/OASISGettext.ml" *) @@ -249,6 +249,9 @@ module MyOCamlbuildFindlib = struct *) open Ocamlbuild_plugin + type conf = + { no_automatic_syntax: bool; + } (* these functions are not really officially exported *) let run_and_read = @@ -315,7 +318,7 @@ module MyOCamlbuildFindlib = struct (* This lists all supported packages. *) let find_packages () = - List.map before_space (split_nl & run_and_read "ocamlfind list") + List.map before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^ " list")) (* Mock to list available syntaxes. *) @@ -338,7 +341,7 @@ module MyOCamlbuildFindlib = struct ] - let dispatch = + let dispatch conf = function | After_options -> (* By using Before_options one let command line options have an higher @@ -357,31 +360,39 @@ module MyOCamlbuildFindlib = struct * -linkpkg *) flag ["ocaml"; "link"; "program"] & A"-linkpkg"; - (* For each ocamlfind package one inject the -package option when - * compiling, computing dependencies, generating documentation and - * linking. *) - List.iter - begin fun pkg -> - let base_args = [A"-package"; A pkg] in - (* TODO: consider how to really choose camlp4o or camlp4r. *) - let syn_args = [A"-syntax"; A "camlp4o"] in - let args = - (* Heuristic to identify syntax extensions: whether they end in - ".syntax"; some might not. - *) - if Filename.check_suffix pkg "syntax" || - List.mem pkg well_known_syntax then - syn_args @ base_args - else - base_args - in - flag ["ocaml"; "compile"; "pkg_"^pkg] & S args; - flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args; - flag ["ocaml"; "doc"; "pkg_"^pkg] & S args; - flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args; - flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args; - end - (find_packages ()); + if not (conf.no_automatic_syntax) then begin + (* For each ocamlfind package one inject the -package option when + * compiling, computing dependencies, generating documentation and + * linking. *) + List.iter + begin fun pkg -> + let base_args = [A"-package"; A pkg] in + (* TODO: consider how to really choose camlp4o or camlp4r. *) + let syn_args = [A"-syntax"; A "camlp4o"] in + let (args, pargs) = + (* Heuristic to identify syntax extensions: whether they end in + ".syntax"; some might not. + *) + if Filename.check_suffix pkg "syntax" || + List.mem pkg well_known_syntax then + (syn_args @ base_args, syn_args) + else + (base_args, []) + in + flag ["ocaml"; "compile"; "pkg_"^pkg] & S args; + flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args; + flag ["ocaml"; "doc"; "pkg_"^pkg] & S args; + flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args; + flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args; + + (* TODO: Check if this is allowed for OCaml < 3.12.1 *) + flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs; + end + (find_packages ()); + end; (* Like -package but for extensions syntax. Morover -syntax is useless * when linking. *) @@ -546,12 +557,13 @@ module MyOCamlbuildBase = struct (* When ocaml link something that use the C library, then one need that file to be up to date. + This holds both for programs and for libraries. *) - dep ["link"; "ocaml"; "program"; tag_libstubs lib] - [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; + dep ["link"; "ocaml"; tag_libstubs lib] + [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; - dep ["compile"; "ocaml"; "program"; tag_libstubs lib] - [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; + dep ["compile"; "ocaml"; tag_libstubs lib] + [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; (* TODO: be more specific about what depends on headers *) (* Depends on .h files *) @@ -580,18 +592,18 @@ module MyOCamlbuildBase = struct () - let dispatch_default t = + let dispatch_default conf t = dispatch_combine [ dispatch t; - MyOCamlbuildFindlib.dispatch; + MyOCamlbuildFindlib.dispatch conf; ] end -# 594 "myocamlbuild.ml" +# 606 "myocamlbuild.ml" open Ocamlbuild_plugin;; let package_default = { @@ -602,8 +614,10 @@ let package_default = } ;; -let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;; +let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false} + +let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;; -# 608 "myocamlbuild.ml" +# 622 "myocamlbuild.ml" (* OASIS_STOP *) Ocamlbuild_plugin.dispatch dispatch_default;; @@ -3,9 +3,9 @@ let () = with Not_found -> ();; (* OASIS_START *) -(* DO NOT EDIT (digest: 570f0cf455bae2020373f483beb84fb7) *) +(* DO NOT EDIT (digest: ed8b6a6d5d6899833e2d5502e0896aa5) *) (* - Regenerated by OASIS v0.4.4 + Regenerated by OASIS v0.4.5 Visit http://oasis.forge.ocamlcore.org for more information and documentation about functions used in this file. *) @@ -244,11 +244,9 @@ module OASISString = struct let replace_chars f s = - let buf = String.make (String.length s) 'X' in - for i = 0 to String.length s - 1 do - buf.[i] <- f s.[i] - done; - buf + let buf = Buffer.create (String.length s) in + String.iter (fun c -> Buffer.add_char buf (f c)) s; + Buffer.contents buf end @@ -1731,6 +1729,13 @@ module OASISFeatures = struct (fun () -> s_ "Allows the OASIS section comments and digest to be omitted in \ generated files.") + + let no_automatic_syntax = + create "no_automatic_syntax" alpha + (fun () -> + s_ "Disable the automatic inclusion of -syntax camlp4o for packages \ + that matches the internal heuristic (if a dependency ends with \ + a .syntax or is a well known syntax).") end module OASISUnixPath = struct @@ -2101,16 +2106,6 @@ module OASISLibrary = struct lst in - (* The headers that should be compiled along *) - let headers = - if lib.lib_pack then - [] - else - find_modules - lib.lib_modules - "cmi" - in - (* The .cmx that be compiled along *) let cmxs = let should_be_built = @@ -2136,12 +2131,32 @@ module OASISLibrary = struct [] in + (* The headers and annot/cmt files that should be compiled along *) + let headers = + let sufx = + if lib.lib_pack + then [".cmti"; ".cmt"; ".annot"] + else [".cmi"; ".cmti"; ".cmt"; ".annot"] + in + List.map + begin + List.fold_left + begin fun accu s -> + let dot = String.rindex s '.' in + let base = String.sub s 0 dot in + List.map ((^) base) sufx @ accu + end + [] + end + (find_modules lib.lib_modules "cmi") + in + (* Compute what libraries should be built *) let acc_nopath = (* Add the packed header file if required *) let add_pack_header acc = if lib.lib_pack then - [cs.cs_name^".cmi"] :: acc + [cs.cs_name^".cmi"; cs.cs_name^".cmti"; cs.cs_name^".cmt"] :: acc else acc in @@ -2501,13 +2516,13 @@ module OASISFindlib = struct in let library_name_of_findlib_name = - Lazy.lazy_from_fun - (fun () -> - (* Revert findlib_name_of_library_name. *) - MapString.fold - (fun k v mp -> MapString.add v k mp) - fndlb_name_of_lib_name - MapString.empty) + lazy begin + (* Revert findlib_name_of_library_name. *) + MapString.fold + (fun k v mp -> MapString.add v k mp) + fndlb_name_of_lib_name + MapString.empty + end in let library_name_of_findlib_name fndlb_nm = try @@ -2877,7 +2892,7 @@ module OASISFileUtil = struct end -# 2878 "setup.ml" +# 2893 "setup.ml" module BaseEnvLight = struct (* # 22 "src/base/BaseEnvLight.ml" *) @@ -2982,7 +2997,7 @@ module BaseEnvLight = struct end -# 2983 "setup.ml" +# 2998 "setup.ml" module BaseContext = struct (* # 22 "src/base/BaseContext.ml" *) @@ -5393,7 +5408,7 @@ module BaseSetup = struct end -# 5394 "setup.ml" +# 5409 "setup.ml" module InternalConfigurePlugin = struct (* # 22 "src/plugins/internal/InternalConfigurePlugin.ml" *) @@ -5829,6 +5844,17 @@ module InternalInstallPlugin = struct lst in + let make_fnames modul sufx = + List.fold_right + begin fun sufx accu -> + (String.capitalize modul ^ sufx) :: + (String.uncapitalize modul ^ sufx) :: + accu + end + sufx + [] + in + (** Install all libraries *) let install_libs pkg = @@ -5849,27 +5875,29 @@ module InternalInstallPlugin = struct OASISHostPath.of_unix bs.bs_path in List.fold_left - (fun acc modul -> - try - List.find - OASISFileUtil.file_exists_case - (List.map - (Filename.concat path) - [modul^".mli"; - modul^".ml"; - String.uncapitalize modul^".mli"; - String.capitalize modul^".mli"; - String.uncapitalize modul^".ml"; - String.capitalize modul^".ml"]) - :: acc - with Not_found -> - begin - warning - (f_ "Cannot find source header for module %s \ - in library %s") - modul cs.cs_name; - acc - end) + begin fun acc modul -> + begin + try + [List.find + OASISFileUtil.file_exists_case + (List.map + (Filename.concat path) + (make_fnames modul [".mli"; ".ml"]))] + with Not_found -> + warning + (f_ "Cannot find source header for module %s \ + in library %s") + modul cs.cs_name; + [] + end + @ + List.filter + OASISFileUtil.file_exists_case + (List.map + (Filename.concat path) + (make_fnames modul [".annot";".cmti";".cmt"])) + @ acc + end acc lib.lib_modules in @@ -5917,27 +5945,29 @@ module InternalInstallPlugin = struct OASISHostPath.of_unix bs.bs_path in List.fold_left - (fun acc modul -> - try - List.find - OASISFileUtil.file_exists_case - (List.map - (Filename.concat path) - [modul^".mli"; - modul^".ml"; - String.uncapitalize modul^".mli"; - String.capitalize modul^".mli"; - String.uncapitalize modul^".ml"; - String.capitalize modul^".ml"]) - :: acc - with Not_found -> - begin - warning - (f_ "Cannot find source header for module %s \ - in object %s") - modul cs.cs_name; - acc - end) + begin fun acc modul -> + begin + try + [List.find + OASISFileUtil.file_exists_case + (List.map + (Filename.concat path) + (make_fnames modul [".mli"; ".ml"]))] + with Not_found -> + warning + (f_ "Cannot find source header for module %s \ + in object %s") + modul cs.cs_name; + [] + end + @ + List.filter + OASISFileUtil.file_exists_case + (List.map + (Filename.concat path) + (make_fnames modul [".annot";".cmti";".cmt"])) + @ acc + end acc obj.obj_modules in @@ -6242,7 +6272,7 @@ module InternalInstallPlugin = struct end -# 6243 "setup.ml" +# 6273 "setup.ml" module OCamlbuildCommon = struct (* # 22 "src/plugins/ocamlbuild/OCamlbuildCommon.ml" *) @@ -6300,6 +6330,11 @@ module OCamlbuildCommon = struct else []; + if bool_of_string (tests ()) then + ["-tag"; "tests"] + else + []; + if bool_of_string (profile ()) then ["-tag"; "profile"] else @@ -6615,7 +6650,7 @@ module OCamlbuildDocPlugin = struct end -# 6616 "setup.ml" +# 6651 "setup.ml" open OASISTypes;; let setup_t = @@ -6644,13 +6679,13 @@ let setup_t = distclean_doc = []; package = { - oasis_version = "0.3"; - ocaml_version = None; + oasis_version = "0.4"; + ocaml_version = Some (OASISVersion.VGreaterEqual "3.12.0"); findlib_version = None; alpha_features = []; beta_features = []; name = "benchmark"; - version = "1.3.1"; + version = "1.4"; license = OASISLicense.DEP5License (OASISLicense.DEP5Unit @@ -6661,7 +6696,8 @@ let setup_t = }); license_file = None; copyrights = []; - maintainers = []; + maintainers = + ["Christophe Troestler <Christophe.Troestler@umons.ac.be>"]; authors = ["Christophe Troestler <Christophe.Troestler@umons.ac.be>"]; homepage = Some "http://ocaml-benchmark.forge.ocamlcore.org/"; @@ -7100,6 +7136,33 @@ let setup_t = bs_nativeopt = [(OASISExpr.EBool true, [])] }, {exec_custom = false; exec_main_is = "long_run.ml"}); + Executable + ({ + cs_name = "tree"; + cs_data = PropList.Data.create (); + cs_plugin_data = [] + }, + { + bs_build = + [ + (OASISExpr.EBool true, false); + (OASISExpr.EFlag "tests", true) + ]; + bs_install = [(OASISExpr.EBool true, false)]; + bs_path = "tests"; + bs_compiled_object = Best; + bs_build_depends = [InternalLibrary "benchmark"]; + bs_build_tools = [ExternalTool "ocamlbuild"]; + bs_c_sources = []; + bs_data_files = []; + bs_ccopt = [(OASISExpr.EBool true, [])]; + bs_cclib = [(OASISExpr.EBool true, [])]; + bs_dlllib = [(OASISExpr.EBool true, [])]; + bs_dllpath = [(OASISExpr.EBool true, [])]; + bs_byteopt = [(OASISExpr.EBool true, [])]; + bs_nativeopt = [(OASISExpr.EBool true, [])] + }, + {exec_custom = false; exec_main_is = "tree.ml"}); SrcRepo ({ cs_name = "trunk"; @@ -7107,12 +7170,11 @@ let setup_t = cs_plugin_data = [] }, { - src_repo_type = Svn; + src_repo_type = Git; src_repo_location = - "svn://scm.ocamlcore.org/svn/ocaml-benchmark/trunk"; + "https://github.com/Chris00/ocaml-benchmark.git"; src_repo_browser = - Some - "https://forge.ocamlcore.org/scm/browser.php?group_id=197"; + Some "https://github.com/Chris00/ocaml-benchmark"; src_repo_module = None; src_repo_branch = None; src_repo_tag = None; @@ -7125,8 +7187,9 @@ let setup_t = plugin_data = [] }; oasis_fn = Some "_oasis"; - oasis_version = "0.4.4"; - oasis_digest = Some "\238n\184a\218\170\1476}\229\165m\203o\128M"; + oasis_version = "0.4.5"; + oasis_digest = + Some "\176\235\183tc\218(\254\224\132\024\180\239\152\198\242"; oasis_exec = None; oasis_setup_args = []; setup_update = false @@ -7134,6 +7197,6 @@ let setup_t = let setup () = BaseSetup.setup setup_t;; -# 7136 "setup.ml" +# 7199 "setup.ml" (* OASIS_STOP *) let () = setup ();; diff --git a/tests/tree.ml b/tests/tree.ml new file mode 100644 index 0000000..52ee2eb --- /dev/null +++ b/tests/tree.ml @@ -0,0 +1,22 @@ +let () = + let open Benchmark.Tree in + "" @> lazy (let create() = Array.init 1_000_000 (fun i -> i) in + Benchmark.latency1 18L create () ) + |> register; + + "map" @> lazy (let a = Array.init 1_000_000 (fun i -> i) in + let f x = x + 1 in + Benchmark.latency1 18L (Array.map f) a ) + |> register; + + "sort" + @> lazy (let a = Array.init 1_000_000 (fun i -> -i) in + Benchmark.latency1 18L (Array.sort compare) a ) + |> register; + + "sort.add" + @> lazy (Benchmark.latency1 18L (fun x -> x + 1) 1) + |> register + +let () = + Benchmark.Tree.run_global () |