1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
open! Base
type t = { sizes : int Queue.t } [@@unboxed]
let create () = { sizes = Queue.create () }
let add t size = Queue.enqueue t.sizes size
let percentiles = [ 0; 50; 75; 90; 95; 99; 100 ]
type row =
{ percentile : int
; size : int
; count : int
}
let print t =
let zeros, sizes = Queue.to_array t.sizes |> Array.partition_tf ~f:(( = ) 0) in
Array.sort sizes ~compare:Int.compare;
let rows =
if Array.is_empty sizes
then []
else
List.map percentiles ~f:(fun percentile ->
let len = Array.length sizes in
let size = len * percentile / 100 |> Int.min (len - 1) |> Array.get sizes in
let count =
match
Array.binary_search sizes ~compare `First_greater_than_or_equal_to size
with
| None -> 0
| Some index -> Array.length sizes - index
in
{ percentile; size; count })
|> List.remove_consecutive_duplicates
~equal:(Comparable.lift Int.equal ~f:(fun row -> row.size))
~which_to_keep:`Last
in
Stdio.printf " %% | size | count\n";
Stdio.printf "----+------+------\n";
if not (Array.is_empty zeros)
then Stdio.printf " - | 0 | %5d\n" (Array.length zeros);
if not (Array.is_empty zeros || Array.is_empty sizes)
then Stdio.printf "----+------+------\n";
List.iter rows ~f:(fun { percentile; size; count } ->
Stdio.printf "%3d | %4d | %5d\n" percentile size count)
;;