freebsd_task:
env:
matrix:
- - OCAML_VERSION: 4.10.1
- OCAML_VERSION: 4.11.1
- pkg_install_script: pkg install -y ocaml-opam gmp gmake pkgconf bash
+ - OCAML_VERSION: 4.12.0
+ pkg_install_script: pkg install -y ocaml-opam gmake bash
ocaml_script: opam init -a --comp=$OCAML_VERSION
dependencies_script: eval `opam env` && opam install -y --deps-only .
build_script: eval `opam env` && dune build @install
-version=0.18.0
+version=0.21.0
disable=true
+### v0.9 2022-07-24 Paris (France)
+
+- Add support of OCaml 5.00 (@kit-ty-kate, #37)
+- Add support for current-bench and fix bad r² for unequal strings (@Zined-Ada, @art-w, #38)
+- Add benchmark with `bechamel` (@Zineb-Ada, @art-w, #38)
+
### v0.8 2021-08-06 Paris (France)
- Fix the check tool on 4.11.0 (@dinosaure, @cfcs, @stedolan, #30)
--- /dev/null
+.PHONY: bench
+bench:
+ dune exec check/check.exe
+ dune exec check/bench.exe
\ No newline at end of file
--- /dev/null
+let seed = "4EygbdYh+v35vvrmD9YYP4byT5E3H7lTeXJiIj+dQnc="
+let seed = Base64.decode_exn seed
+
+let seed =
+ let res = Array.make (String.length seed / 2) 0 in
+ for i = 0 to (String.length seed / 2) - 1 do
+ res.(i) <- (Char.code seed.[i * 2] lsl 8) lor Char.code seed.[(i * 2) + 1]
+ done;
+ res
+
+let () =
+ let random_seed = seed in
+ Random.full_init random_seed
+
+let random length =
+ let get _ =
+ match Random.int (10 + 26 + 26) with
+ | n when n < 10 -> Char.(chr (code '0' + n))
+ | n when n < 10 + 26 -> Char.(chr (code 'a' + n - 10))
+ | n -> Char.(chr (code 'A' + n - 10 - 26))
+ in
+ String.init length get
+
+open Bechamel
+open Toolkit
+
+let hash_eq_0 = random 4096
+let hash_eq_1 = Bytes.to_string (Bytes.of_string hash_eq_0)
+let chr_into_hash_eq_0 = hash_eq_0.[Random.int 4096]
+let hash_neq_0 = random 4096
+
+let hash_neq_1 =
+ let rec go limit =
+ if limit <= 0 then failwith "Impossible to generate different hashes.";
+ let res = random 4096 in
+ if res = hash_neq_0 then go (pred limit) else res
+ in
+ go 10
+
+let random_chr =
+ let rec go limit =
+ if limit <= 0 then
+ failwith
+ "Impossible to generate a byte which does not appear into hash_neq_0.";
+ let res = Char.chr (Random.int 256) in
+ if not (String.contains hash_neq_0 res) then res else go (pred limit)
+ in
+ go 10
+
+let test_equal0 =
+ Test.make ~name:"equal"
+ (Staged.stage @@ fun () -> Eqaf.equal hash_eq_0 hash_eq_1)
+
+let test_equal1 =
+ Test.make ~name:"not equal"
+ (Staged.stage @@ fun () -> Eqaf.equal hash_neq_0 hash_neq_1)
+
+let cfg = Benchmark.cfg ~start:100
+
+let test_compare0 =
+ Test.make ~name:"equal"
+ (Staged.stage @@ fun () -> Eqaf.compare_be hash_eq_0 hash_eq_1)
+let test_compare1 =
+ Test.make ~name:"not equal"
+ (Staged.stage @@ fun () -> Eqaf.compare_be hash_neq_0 hash_neq_1)
+
+let f_eq_0 (v : int) = v = Char.code chr_into_hash_eq_0
+let f_neq_0 (v : int) = v = Char.code random_chr
+
+let test_exists0 =
+ Test.make ~name:"equal"
+ (Staged.stage @@ fun () -> Eqaf.exists_uint8 ~f:f_eq_0 hash_eq_0)
+let test_exists1 =
+ Test.make ~name:"not equal"
+ (Staged.stage @@ fun () -> Eqaf.exists_uint8 ~f:f_neq_0 hash_neq_0)
+
+let f_hash_eq_0 (v : int) = v = Char.code chr_into_hash_eq_0
+let f_random (v : int) = v = Char.code random_chr
+
+let test_find0 =
+ Test.make ~name:"equal"
+ (Staged.stage @@ fun () -> Eqaf.find_uint8 ~f:f_hash_eq_0 hash_eq_0)
+let test_find1 =
+ Test.make ~name:"not equal"
+ (Staged.stage @@ fun () -> Eqaf.find_uint8 ~f:f_random hash_neq_0)
+
+let benchmark () =
+ let ols =
+ Analyze.ols ~bootstrap:0 ~r_square:true ~predictors:Measure.[| run |]
+ in
+ let instances =
+ Instance.[ monotonic_clock ]
+ in
+ let cfg =
+ Benchmark.cfg ~limit:2000 ~stabilize:true ~quota:(Time.second 1.)
+ ~start:1000 ~kde:(Some 1000) ()
+ in
+ let test_equal =
+ Test.make_grouped ~name:"equal" ~fmt:"%s %s"
+ [ test_equal0; test_equal1 ]
+ in
+ let test_compare =
+ Test.make_grouped ~name:"compare" ~fmt:"%s %s"
+ [ test_compare0; test_compare1 ]
+ in
+ let test_exists =
+ Test.make_grouped ~name:"exists" ~fmt:"%s %s"
+ [ test_exists0; test_exists1 ]
+ in
+ let test_find =
+ Test.make_grouped ~name:"find" ~fmt:"%s %s"
+ [ test_find0; test_find1 ]
+ in
+ let raw_results =
+ Benchmark.all cfg instances
+ (Test.make_grouped ~name:"benchmark" ~fmt:"%s %s"
+ [ test_equal; test_compare; test_exists; test_find ])
+ in
+ let results =
+ List.map (fun instance -> Analyze.all ols instance raw_results) instances
+ in
+ let pr_bench name value =
+ Format.printf
+ {|{"results": [{"name": "eqaf", "metrics": [{"name": "%s", "value": %f, "units": "ns"}]}]}@.|}
+ name value
+ in
+ let results = Analyze.merge ols instances results in
+ let timings = Hashtbl.find results "monotonic-clock" in
+ Hashtbl.iter
+ (fun c v ->
+ match Analyze.OLS.estimates v with
+ | None -> ()
+ | Some ts -> List.iter (pr_bench c) ts)
+ timings;
+ ()
+
+let () = benchmark ()
\ No newline at end of file
let reset = ignore and switch = ignore
let stdlib_true () = String.equal hash_eq_0 hash_eq_1
- let stdlib_false () = String.equal hash_neq_0 hash_neq_1
-
+ let stdlib_false () =
+ for _ = 1 to 100
+ do let _ = String.equal hash_neq_0 hash_neq_1 in () done ;
+ String.equal hash_neq_0 hash_neq_1
+
let eqaf_true () = Eqaf.equal hash_eq_0 hash_eq_1
let eqaf_false () = Eqaf.equal hash_neq_0 hash_neq_1
end)
let reset = ignore and switch = ignore
let stdlib_true () = String.compare hash_eq_0 hash_eq_1
- let stdlib_false () = String.compare hash_neq_0 hash_neq_1
+ let stdlib_false () =
+ for _ = 1 to 100
+ do let _ = String.compare hash_neq_0 hash_neq_1 in () done ;
+ String.compare hash_neq_0 hash_neq_1
let eqaf_true () = Eqaf.compare_be hash_eq_0 hash_eq_1
let eqaf_false () = Eqaf.compare_be hash_neq_0 hash_neq_1
if tried > 20 then invalid_arg "Too many tried for Eqaf.divmod" ;
let res = Divmod32.test () in
if res = exit_success then tried else _4 (succ tried) in
-
+ let pr_bench name value =
+ Fmt.pr {|{"results": [{"name": "check", "metrics": [{"name": "%s", "value": %d}]}]}@.|} name value in
+
let _0 = _0 1 in
Fmt.pr "%d trial(s) for Eqaf.equal.\n%!" _0 ;
+ pr_bench "equal" _0 ;
let _1 = _1 1 in
Fmt.pr "%d trial(s) for Eqaf.compare.\n%!" _1 ;
+ pr_bench "compare" _1 ;
let _2 = _2 1 in
Fmt.pr "%d trial(s) for Eqaf.exists.\n%!" _2 ;
+ pr_bench "exists" _2 ;
let _3 = _3 1 in
Fmt.pr "%d trial(s) for Eqaf.find_uint8.\n%!" _3 ;
+ pr_bench "find_uint8" _3 ;
let _4 = _4 1 in
- Fmt.pr "%d trial(s) for Eqaf.divmod.\n%!" _3 ;
+ Fmt.pr "%d trial(s) for Eqaf.divmod.\n%!" _4 ;
+ pr_bench "divmod" _4 ;
- exit exit_success
+ exit exit_success
\ No newline at end of file
(modules check linear_algebra benchmark fmt unsafe)
(libraries eqaf base64 clock))
+(executable
+ (name bench)
+ (modules bench)
+ (libraries bechamel eqaf base64))
+
(rule
(copy %{read:../config/which-unsafe-file} unsafe.ml))
+#define CAML_NAME_SPACE
+
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
if (clock_gettime(CLOCK_MONOTONIC, &ts))
caml_invalid_argument("clock: unsupported clock");
- return copy_int64(ts.tv_sec * 1000000000LL + ts.tv_nsec);
+ return caml_copy_int64(ts.tv_sec * 1000000000LL + ts.tv_nsec);
}
// XXX(dinosaure): commented because to be able to compile the test into any
now = mach_absolute_time();
- return copy_int64(now * s.numer / s.denom);
+ return caml_copy_int64(now * s.numer / s.denom);
}
QueryPerformanceCounter(&now);
- res = copy_int64(now.QuadPart * frequency.QuadPart);
+ res = caml_copy_int64(now.QuadPart * frequency.QuadPart);
CAMLreturn(res);
}
(lang dune 2.0)
(name eqaf)
-(version v0.8)
+(version v0.9)
-version: "0.8"
+version: "0.9"
opam-version: "2.0"
maintainer: [ "Romain Calascibetta <romain.calascibetta@gmail.com>" ]
authors: [ "Romain Calascibetta <romain.calascibetta@gmail.com>" ]
"base64" {with-test}
"alcotest" {with-test}
"crowbar" {with-test}
+ "fmt" {with-test & >= "0.8.7"}
+ "bechamel" {with-test}
]
\ No newline at end of file
let value w = Alcotest.testable Fmt.int (equal w)
let be a b expected =
- let title = Fmt.strf "be %S %S = %d" a b expected in
+ let title = Fmt.str "be %S %S = %d" a b expected in
Alcotest.test_case title `Quick @@ fun () ->
let expected' = String.compare a b in
Alcotest.(check (value (of_expected expected))) "result" (Eqaf.compare_be a b) expected ;
Alcotest.(check (value (of_expected expected'))) "string.compare" (Eqaf.compare_be a b) expected'
let le a b expected =
- let title = Fmt.strf "le %S %S = %d" a b expected in
+ let title = Fmt.str "le %S %S = %d" a b expected in
Alcotest.test_case title `Quick @@ fun () ->
Alcotest.(check (value (of_expected expected))) "result" (Eqaf.compare_le a b) expected
let exists str chr exists =
- Alcotest.test_case (Fmt.strf "contains %S %c = %b" str chr exists) `Quick @@ fun () ->
+ Alcotest.test_case (Fmt.str "contains %S %c = %b" str chr exists) `Quick @@ fun () ->
let res = Eqaf.exists_uint8 ~f:((=) (Char.code chr)) str in
Alcotest.(check bool) "result" res exists
let find str chr index =
- Alcotest.test_case (Fmt.strf "index %S %c = %d" str chr index) `Quick @@ fun () ->
+ Alcotest.test_case (Fmt.str "index %S %c = %d" str chr index) `Quick @@ fun () ->
let res = Eqaf.find_uint8 ~f:((=) (Char.code chr)) str in
Alcotest.(check int) "result" res index
let int_of_bool bool expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
"int_of_bool %B = %d" bool expect
) `Quick @@ fun ()->
Alcotest.(check int) "result" expect (Eqaf.int_of_bool bool)
let bool_of_int desc n expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
"int_of_bool %s = %B" desc expect
) `Quick @@ fun ()->
Alcotest.(check bool) "result" expect (Eqaf.bool_of_int n)
let select_a_if_in_range (low,high) n a b expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
"select_a_if_in_range (%d,%d) ~n:%d %d %d"
low high n a b
) `Quick @@ fun ()->
let divmod str x m q r =
(* (x / m = q) and (x mod m = r) *)
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
"divmod %s %lu / %lu = %lu, %lu mod %lu = %lu"
str x m q x m r
) `Quick @@ fun ()->
let ascii_of_int32 str digits n expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
"ascii_of_string %s %d %lu %S"
str digits n expect
) `Quick @@ fun ()->
let string_of_hex str hex expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
" %s %S %S"
str hex expect
) `Quick @@ fun ()->
let hex_of_string str raw expect =
Alcotest.test_case
- (Fmt.strf
+ (Fmt.str
" %s %S %S"
str raw expect
) `Quick @@ fun ()->