Skip to content

Commit cdab040

Browse files
authored
Merge pull request #38 from dinosaure/avoid-unsigned-to-int
Avoid an 'a option allocation when we cast a int32 into a int on 64-bit architecture
2 parents c2a991f + 87db12a commit cdab040

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

bench/checksum.ml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
open Bechamel
2+
open Toolkit
3+
4+
let payload =
5+
let ln = 3_000 in
6+
let ba = Bigarray.(Array1.create char c_layout ln) in
7+
Bigarray.Array1.fill ba '\xff'; ba
8+
9+
let checksum = Staged.stage @@ fun () ->
10+
ignore (Utcp.Checksum.digest payload)
11+
12+
let test =
13+
Test.make ~name:"checksum" checksum
14+
15+
let benchmark () =
16+
let ols = Analyze.ols ~bootstrap:0 ~r_square:true ~predictors:Measure.[| run |] in
17+
let instances = Instance.[ monotonic_clock ] in
18+
let cfg = Benchmark.cfg ~limit:2000 ~stabilize:true ~quota:(Time.second 1.) ~kde:(Some 1000) () in
19+
let raw = Benchmark.all cfg instances test in
20+
let results = List.map (fun inst -> Analyze.all ols inst raw) instances in
21+
let results = Analyze.merge ols instances results in
22+
(results, raw)
23+
24+
let nothing _ = Ok ()
25+
26+
let () =
27+
let results = benchmark () in
28+
let results =
29+
let open Bechamel_js in
30+
emit ~dst:(Channel stdout) nothing ~x_label:Measure.run
31+
~y_label:(Measure.label Instance.monotonic_clock) results in
32+
match results with Ok () -> () | Error (`Msg err) -> failwith err

bench/dune

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(executable
2+
(name checksum)
3+
(libraries bechamel bechamel-js utcp))
4+
5+
(rule
6+
(targets checksum.json)
7+
(action (with-stdout-to %{targets} (run ./checksum.exe))))
8+
9+
(rule
10+
(targets checksum.html)
11+
(action (system "%{bin:bechamel-html} < %{dep:checksum.json} > %{targets}")))

src/checksum.ml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ external unsafe_get_uint8 : bigstring -> int -> int = "%caml_ba_unsafe_ref_1"
2323
external unsafe_get_uint16 : bigstring -> int -> int = "%caml_bigstring_get16u"
2424
external swap16 : int -> int = "%bswap16"
2525
external swap32 : int32 -> int32 = "%bswap_int32"
26+
external int32_to_int : int32 -> int = "%int32_to_int"
27+
28+
let mask = 0xffff lsl 16 lor 0xffff
29+
let int32_to_int n = int32_to_int n land mask
30+
31+
(* NOTE(dinosaure): Users may wonder why we use access with a bound-check (such
32+
as [bufX.{...}]). The reason is simple: OCaml, with regard to bigarrays, can
33+
unbox [int16]/[int32] if such access is desired. Furthermore, using a
34+
function such as [unsafe_get_int{16,32}] would not allow OCaml to correctly
35+
infer this access and to "prepare the ground" for unboxing. It should be
36+
noted that bound-check is not the most expensive (and quite predictable in
37+
reality), but unbox is. *)
2638

2739
let unsafe_digest_16_le ?(off = 0) ~len:top buf =
2840
let buf16 = to_int16 ~off ~len:top buf in
@@ -40,13 +52,14 @@ let unsafe_digest_16_le ?(off = 0) ~len:top buf =
4052
if !sum > 0xffff then incr sum;
4153
swap16 (lnot !sum land 0xffff)
4254

55+
(* NOTE(dinosaure): only work on 64-bit architecture. *)
4356
let unsafe_digest_32_le ?(off = 0) ~len:top buf =
4457
let buf32 = to_int32 ~off ~len:top buf in
4558
let len = ref top in
4659
let sum = ref 0 in
4760
let i = ref 0 in
4861
while !len >= 4 do
49-
let[@warning "-8"] (Some v) = Int32.unsigned_to_int buf32.{!i} in
62+
let v = int32_to_int buf32.{!i} in
5063
sum := !sum + v;
5164
incr i;
5265
len := !len - 4
@@ -60,13 +73,14 @@ let unsafe_digest_32_le ?(off = 0) ~len:top buf =
6073
done;
6174
swap16 (lnot !sum land 0xffff)
6275

76+
(* NOTE(dinosaure): only work on 64-bit architecture. *)
6377
let unsafe_digest_32_be ?(off = 0) ~len:top buf =
6478
let buf32 = to_int32 ~off ~len:top buf in
6579
let len = ref top in
6680
let sum = ref 0 in
6781
let i = ref 0 in
6882
while !len >= 4 do
69-
let[@warning "-8"] (Some v) = Int32.unsigned_to_int (swap32 buf32.{!i}) in
83+
let v = int32_to_int (swap32 buf32.{!i}) in
7084
sum := !sum + v;
7185
incr i;
7286
len := !len - 4

utcp.opam

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ depends: [
3636
"pcap-format" {>= "0.6.0" & dev}
3737
"alcotest" {>= "1.5.0" & with-test}
3838
"crowbar" {>= "0.2.1" & with-test}
39+
"bechamel" {with-test}
40+
"bechamel-js" {with-test}
3941
]
4042
build: [
4143
["dune" "subst"] {dev}

0 commit comments

Comments
 (0)