]> Cypherpunks.ru repositories - gostls13.git/blob - test/typeparam/metrics.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / typeparam / metrics.go
1 // run
2
3 // Copyright 2021 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Package metrics provides tracking arbitrary metrics composed of
8 // values of comparable types.
9 package main
10
11 import (
12         "fmt"
13         "sort"
14         "sync"
15 )
16
17 // _Metric1 tracks metrics of values of some type.
18 type _Metric1[T comparable] struct {
19         mu sync.Mutex
20         m  map[T]int
21 }
22
23 // Add adds another instance of some value.
24 func (m *_Metric1[T]) Add(v T) {
25         m.mu.Lock()
26         defer m.mu.Unlock()
27         if m.m == nil {
28                 m.m = make(map[T]int)
29         }
30         m.m[v]++
31 }
32
33 // Count returns the number of instances we've seen of v.
34 func (m *_Metric1[T]) Count(v T) int {
35         m.mu.Lock()
36         defer m.mu.Unlock()
37         return m.m[v]
38 }
39
40 // Metrics returns all the values we've seen, in an indeterminate order.
41 func (m *_Metric1[T]) Metrics() []T {
42         return _Keys(m.m)
43 }
44
45 type key2[T1, T2 comparable] struct {
46         f1 T1
47         f2 T2
48 }
49
50 // _Metric2 tracks metrics of pairs of values.
51 type _Metric2[T1, T2 comparable] struct {
52         mu sync.Mutex
53         m  map[key2[T1, T2]]int
54 }
55
56 // Add adds another instance of some pair of values.
57 func (m *_Metric2[T1, T2]) Add(v1 T1, v2 T2) {
58         m.mu.Lock()
59         defer m.mu.Unlock()
60         if m.m == nil {
61                 m.m = make(map[key2[T1, T2]]int)
62         }
63         m.m[key2[T1, T2]{v1, v2}]++
64 }
65
66 // Count returns the number of instances we've seen of v1/v2.
67 func (m *_Metric2[T1, T2]) Count(v1 T1, v2 T2) int {
68         m.mu.Lock()
69         defer m.mu.Unlock()
70         return m.m[key2[T1, T2]{v1, v2}]
71 }
72
73 // Metrics returns all the values we've seen, in an indeterminate order.
74 func (m *_Metric2[T1, T2]) Metrics() (r1 []T1, r2 []T2) {
75         for _, k := range _Keys(m.m) {
76                 r1 = append(r1, k.f1)
77                 r2 = append(r2, k.f2)
78         }
79         return r1, r2
80 }
81
82 type key3[T1, T2, T3 comparable] struct {
83         f1 T1
84         f2 T2
85         f3 T3
86 }
87
88 // _Metric3 tracks metrics of triplets of values.
89 type _Metric3[T1, T2, T3 comparable] struct {
90         mu sync.Mutex
91         m  map[key3[T1, T2, T3]]int
92 }
93
94 // Add adds another instance of some triplet of values.
95 func (m *_Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) {
96         m.mu.Lock()
97         defer m.mu.Unlock()
98         if m.m == nil {
99                 m.m = make(map[key3[T1, T2, T3]]int)
100         }
101         m.m[key3[T1, T2, T3]{v1, v2, v3}]++
102 }
103
104 // Count returns the number of instances we've seen of v1/v2/v3.
105 func (m *_Metric3[T1, T2, T3]) Count(v1 T1, v2 T2, v3 T3) int {
106         m.mu.Lock()
107         defer m.mu.Unlock()
108         return m.m[key3[T1, T2, T3]{v1, v2, v3}]
109 }
110
111 // Metrics returns all the values we've seen, in an indeterminate order.
112 func (m *_Metric3[T1, T2, T3]) Metrics() (r1 []T1, r2 []T2, r3 []T3) {
113         for k := range m.m {
114                 r1 = append(r1, k.f1)
115                 r2 = append(r2, k.f2)
116                 r3 = append(r3, k.f3)
117         }
118         return r1, r2, r3
119 }
120
121 type S struct{ a, b, c string }
122
123 func TestMetrics() {
124         m1 := _Metric1[string]{}
125         if got := m1.Count("a"); got != 0 {
126                 panic(fmt.Sprintf("Count(%q) = %d, want 0", "a", got))
127         }
128         m1.Add("a")
129         m1.Add("a")
130         if got := m1.Count("a"); got != 2 {
131                 panic(fmt.Sprintf("Count(%q) = %d, want 2", "a", got))
132         }
133         if got, want := m1.Metrics(), []string{"a"}; !_SlicesEqual(got, want) {
134                 panic(fmt.Sprintf("Metrics = %v, want %v", got, want))
135         }
136
137         m2 := _Metric2[int, float64]{}
138         m2.Add(1, 1)
139         m2.Add(2, 2)
140         m2.Add(3, 3)
141         m2.Add(3, 3)
142         k1, k2 := m2.Metrics()
143
144         sort.Ints(k1)
145         w1 := []int{1, 2, 3}
146         if !_SlicesEqual(k1, w1) {
147                 panic(fmt.Sprintf("_Metric2.Metrics first slice = %v, want %v", k1, w1))
148         }
149
150         sort.Float64s(k2)
151         w2 := []float64{1, 2, 3}
152         if !_SlicesEqual(k2, w2) {
153                 panic(fmt.Sprintf("_Metric2.Metrics first slice = %v, want %v", k2, w2))
154         }
155
156         m3 := _Metric3[string, S, S]{}
157         m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
158         m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
159         m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
160         m3.Add("b", S{"d", "e", "f"}, S{"g", "h", "i"})
161         if got := m3.Count("a", S{"d", "e", "f"}, S{"g", "h", "i"}); got != 3 {
162                 panic(fmt.Sprintf("Count(%v, %v, %v) = %d, want 3", "a", S{"d", "e", "f"}, S{"g", "h", "i"}, got))
163         }
164 }
165
166 func main() {
167         TestMetrics()
168 }
169
170 // _Equal reports whether two slices are equal: the same length and all
171 // elements equal. All floating point NaNs are considered equal.
172 func _SlicesEqual[Elem comparable](s1, s2 []Elem) bool {
173         if len(s1) != len(s2) {
174                 return false
175         }
176         for i, v1 := range s1 {
177                 v2 := s2[i]
178                 if v1 != v2 {
179                         isNaN := func(f Elem) bool { return f != f }
180                         if !isNaN(v1) || !isNaN(v2) {
181                                 return false
182                         }
183                 }
184         }
185         return true
186 }
187
188 // _Keys returns the keys of the map m.
189 // The keys will be an indeterminate order.
190 func _Keys[K comparable, V any](m map[K]V) []K {
191         r := make([]K, 0, len(m))
192         for k := range m {
193                 r = append(r, k)
194         }
195         return r
196 }