-
Notifications
You must be signed in to change notification settings - Fork 38
/
bench-tuple.jl
131 lines (118 loc) · 3.76 KB
/
bench-tuple.jl
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module BenchTuple
using BenchmarkTools
using Statistics
using Gadfly
using MLStyle
using DataFrames
import Match
import Rematch
using ..ArbitrarySampler
using ..Utils
mod′(n) = x -> mod(x, n)
len_in(rng) = x -> length(x) in rng
is_in(rng) = x -> x in rng
integer20 = @spec ::Integer isa mod′(20)
struct UserTy{T}
a::T
b::Symbol
end
@as_record UserTy
specs = [
:spec1 => (@spec (1, (_, "2", _), ("3", 4, 5))),
:spec2 => (@spec (_, "1", 2, _, (3, "4", _), _)),
:spec3 => (@spec (_, 1, _, 2, _, 3, _, 4, _, 5)),
:spec4 => (@spec ((1, 2, 3, _), (4, 5, 6, _, (7, 8, 9, _, (11, 12, 13))))),
:spec5 => (@spec (::String, ::Symbol, ::Real, ([1, _], UserTy(:a, :b)))),
:_ => @spec(_),
]
implementations = [
:MLStyle => (@λ begin
(1, (_, "2", _), ("3", 4, 5)) -> 1
(_, "1", 2, _, (3, "4", _), _) -> 2
(_, 1, _, 2, _, 3, _, 4, _, 5) -> 3
((1, 2, 3, _), (4, 5, 6, _, (7, 8, 9, _, (11, 12, 13)))) -> 4
_ -> 5
end),
:Rematch => function (x)
Rematch.@match x begin
(1, (_, "2", _), ("3", 4, 5)) => 1
(_, "1", 2, _, (3, "4", _), _) => 2
(_, 1, _, 2, _, 3, _, 4, _, 5) => 3
((1, 2, 3, _), (4, 5, 6, _, (7, 8, 9, _, (11, 12, 13)))) => 4
_ => 5
end
end,
Symbol("Match.jl") => function (x)
Match.@match x begin
(1, (_, "2", _), ("3", 4, 5)) => 1
(_, "1", 2, _, (3, "4", _), _) => 2
(_, 1, _, 2, _, 3, _, 4, _, 5) => 3
((1, 2, 3, _), (4, 5, 6, _, (7, 8, 9, _, (11, 12, 13)))) => 4
_ => 5
end
end,
:HandWritten => function (tp)
!(tp isa Tuple) ? 5 :
let n = length(tp)
if n === 3 && tp[1] === 1
tp_ = tp[2]
if !(tp isa Tuple) || tp_[2] != "2"
return 5
end
tp[3] == ("3", 4, 5) ? 1 : 5
elseif n === 6 && tp[2] == "1" && tp[3] === 2
tp = tp[5]
!(tp isa Tuple) ? 5 : tp[1] === 3 && tp[2] == "4" ? 2 : 5
elseif n === 10 &&
tp[2] === 1 &&
tp[4] === 2 &&
tp[6] === 3 &&
tp[8] === 4 &&
tp[10] === 5
3
elseif n === 2 && tp[1] isa Tuple && tp[2] isa Tuple
@inline eqtp(a, slice, v) =
all(slice) do i
a[i] === v[i]
end
(a, b) = tp
if eqtp(a, 1:3, (1, 2, 3)) &&
eqtp(b, 1:3, (4, 5, 6)) &&
let a = b[5]
eqtp(a, 1:3, (7, 8, 9)) && a[5] === (11, 12, 13)
end
4
end
else
5
end
end
end,
]
records = NamedTuple{(:time_mean, :implementation, :case)}[]
for (spec_id, spec) in specs
# group_key = string(spec_id)
# suite[group_key] = BenchmarkGroup()
for (impl_id, impl_fn) in implementations
bench′ =
@benchmark $impl_fn(sample) setup = (sample = $generate($spec)) samples = 2000
time′ = mean(bench′.times)
@info :bench (spec_id, impl_id, time′)
push!(records, (time_mean = time′, implementation = impl_id, case = spec_id))
end
end
df = DataFrame(records)
@info df
theme = Theme(
guide_title_position = :left,
colorkey_swatch_shape = :circle,
minor_label_font = "Consolas",
major_label_font = "Consolas",
point_size = 5px,
)
report_meantime, df_time = report(df, Guide.title("Tuples"); benchfield = :time_mean)
open("stats/bench-tuple.txt", "w") do f
write(f, string(df))
end
draw(SVG("stats/bench-tuple.svg", 14inch, 6inch), report_meantime)
end