This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
140
unikernel/duniverse/eqaf/test/test_branch.ml
Normal file
140
unikernel/duniverse/eqaf/test/test_branch.ml
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
let exit_success = 0
|
||||
let exit_failure = 1
|
||||
|
||||
(* First computation wants to count operations needed by
|
||||
- one_if_not_zero
|
||||
- zero_if_not_zero
|
||||
- select_int
|
||||
|
||||
For each /assembly instructions/, we update a counter. This way is not
|
||||
totally true. Even if we check by hands that bitwise operations don't
|
||||
emit branches, this is our only assumption! *)
|
||||
|
||||
let operation = ref 0
|
||||
|
||||
let logical_shift_right a b = incr operation ; a lsr b
|
||||
let logical_or a b = incr operation ; a lor b
|
||||
let shift_right a b = incr operation ; a asr b
|
||||
let logical_and a b = incr operation ; a land b
|
||||
let logical_not a = incr operation ; lnot a
|
||||
let minus a = incr operation ; (- a)
|
||||
let sub a b = incr operation ; a - b
|
||||
|
||||
let[@inline always] minus_one_or_less n =
|
||||
logical_shift_right n (sub Sys.int_size 1)
|
||||
|
||||
let[@inline always] one_if_not_zero n = minus_one_or_less (logical_or (minus n) n)
|
||||
let[@inline always] zero_if_not_zero n = sub (one_if_not_zero n) 1
|
||||
let[@inline always] select_int choose_b a b =
|
||||
let mask = shift_right (logical_or (minus choose_b) choose_b) Sys.int_size in
|
||||
logical_or (logical_and a (logical_not mask)) (logical_and b mask)
|
||||
|
||||
let one_if_not_zero_ops =
|
||||
let _ = one_if_not_zero 0x7eadbeef in
|
||||
Format.printf "[one_if_not_zero]: %d operation(s).\n%!" !operation ;
|
||||
!operation
|
||||
|
||||
let () = operation := 0
|
||||
|
||||
let zero_if_not_zero_ops =
|
||||
let _ = zero_if_not_zero 0x7eadbeef in
|
||||
Format.printf "[zero_if_not_zero]: %d operation(s).\n%!" !operation ;
|
||||
!operation
|
||||
|
||||
let () = operation := 0
|
||||
|
||||
let select_int_ops =
|
||||
let _ = select_int 0 1 2 in
|
||||
Format.printf "[select_int]: %d operation(s).\n%!" !operation ;
|
||||
!operation
|
||||
|
||||
let eqaf_sleep () = Unix.sleep 1
|
||||
|
||||
let logical_shift_right a b = eqaf_sleep () ; a lsr b
|
||||
let logical_or a b = eqaf_sleep () ; a lor b
|
||||
let shift_right a b = eqaf_sleep () ; a asr b
|
||||
let logical_and a b = eqaf_sleep () ; a land b
|
||||
let logical_not a = eqaf_sleep () ; lnot a
|
||||
let minus a = eqaf_sleep () ; (- a)
|
||||
let sub a b = eqaf_sleep () ; a - b
|
||||
|
||||
let[@inline always] minus_one_or_less n =
|
||||
logical_shift_right n (sub Sys.int_size 1)
|
||||
|
||||
let[@inline always] one_if_not_zero n = minus_one_or_less (logical_or (minus n) n)
|
||||
let[@inline always] zero_if_not_zero n = sub (one_if_not_zero n) 1
|
||||
let[@inline always] select_int choose_b a b =
|
||||
let mask = shift_right (logical_or (minus choose_b) choose_b) Sys.int_size in
|
||||
logical_or (logical_and a (logical_not mask)) (logical_and b mask)
|
||||
|
||||
(* Finally, we count how many time we spend when we call our
|
||||
functions. [eqaf_sleep] spends 1 second, so our bitwise operators
|
||||
should spend 1 second + some nanosecond. At the end, execution of
|
||||
them should be closely equal to our operation counter where:
|
||||
|
||||
1 operation ~= 1 second
|
||||
|
||||
To be able to count time, we use [caml_time] which is available only
|
||||
on Linux and for a native compilation (see [@unboxed]). Because bitwise
|
||||
operation spend at least 1 second, we finally [floor] our results to
|
||||
delete noise.
|
||||
|
||||
NOTE: [check/check] does a linear regression to delete noise and really
|
||||
get how long is our functions. We think that for our functions:
|
||||
- zero_if_not_zero
|
||||
- one_if_not_zero
|
||||
- select_int
|
||||
[check/check] is too huge. *)
|
||||
|
||||
let time () = Clock.now ()
|
||||
|
||||
let fdiv a b = a /. b
|
||||
|
||||
let () =
|
||||
let t0 = time () in
|
||||
let _ = one_if_not_zero 0x7eadbeef in
|
||||
let t1 = time () in
|
||||
let v0 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[one_if_not_zero 0x7eadbeef]: %fs.\n%!" v0 ;
|
||||
let t0 = time () in
|
||||
let _ = one_if_not_zero 0x0 in
|
||||
let t1 = time () in
|
||||
let v1 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[one_if_not_zero 0x0]: %fs.\n%!" v0 ;
|
||||
if v0 = v1
|
||||
&& int_of_float v0 = one_if_not_zero_ops
|
||||
&& int_of_float v1 = one_if_not_zero_ops
|
||||
then () else exit exit_failure
|
||||
|
||||
let () =
|
||||
let t0 = time () in
|
||||
let _ = zero_if_not_zero 0x7eadbeef in
|
||||
let t1 = time () in
|
||||
let v0 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[zero_if_not_zero 0x7eadbeef]: %fs.\n%!" v0 ;
|
||||
let t0 = time () in
|
||||
let _ = zero_if_not_zero 0x0 in
|
||||
let t1 = time () in
|
||||
let v1 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[zero_if_not_zero 0x0]: %fs.\n%!" v0 ;
|
||||
if v0 = v1
|
||||
&& int_of_float v0 = zero_if_not_zero_ops
|
||||
&& int_of_float v1 = zero_if_not_zero_ops
|
||||
then () else exit exit_failure
|
||||
|
||||
let () =
|
||||
let t0 = time () in
|
||||
let _ = select_int 0 1 2 in
|
||||
let t1 = time () in
|
||||
let v0 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[select_int 0 1 2]: %fs.\n%!" v0 ;
|
||||
let t0 = time () in
|
||||
let _ = select_int 2 1 0 in
|
||||
let t1 = time () in
|
||||
let v1 = Int64.(floor (fdiv (to_float (sub t1 t0)) 1000000000.)) in
|
||||
Format.printf "[select_int 2 1 0]: %fs.\n%!" v1 ;
|
||||
if v0 = v1
|
||||
&& int_of_float v0 = select_int_ops
|
||||
&& int_of_float v1 = select_int_ops
|
||||
then () else exit exit_failure
|
||||
;;
|
||||
Loading…
Add table
Add a link
Reference in a new issue