44package attribute // import "go.opentelemetry.io/otel/attribute"
55
66import (
7+ "cmp"
78 "encoding/json"
89 "reflect"
10+ "slices"
911 "sort"
10- "sync"
1112)
1213
1314type (
@@ -37,10 +38,11 @@ type (
3738 iface interface {}
3839 }
3940
40- // Sortable implements sort.Interface, used for sorting KeyValue. This is
41- // an exported type to support a memory optimization. A pointer to one of
42- // these is needed for the call to sort.Stable(), which the caller may
43- // provide in order to avoid an allocation. See NewSetWithSortable().
41+ // Sortable implements sort.Interface, used for sorting KeyValue.
42+ //
43+ // Deprecated: This type is no longer used. It was added as a performance
44+ // optimization for Go < 1.21 that is no longer needed (Go < 1.21 is no
45+ // longer supported by the module).
4446 Sortable []KeyValue
4547)
4648
5456 iface : [0 ]KeyValue {},
5557 },
5658 }
57-
58- // sortables is a pool of Sortables used to create Sets with a user does
59- // not provide one.
60- sortables = sync.Pool {
61- New : func () interface {} { return new (Sortable ) },
62- }
6359)
6460
6561// EmptySet returns a reference to a Set with no elements.
@@ -185,26 +181,18 @@ func empty() Set {
185181// Except for empty sets, this method adds an additional allocation compared
186182// with calls that include a Sortable.
187183func NewSet (kvs ... KeyValue ) Set {
188- // Check for empty set.
189- if len (kvs ) == 0 {
190- return empty ()
191- }
192- srt := sortables .Get ().(* Sortable )
193- s , _ := NewSetWithSortableFiltered (kvs , srt , nil )
194- sortables .Put (srt )
184+ s , _ := NewSetWithFiltered (kvs , nil )
195185 return s
196186}
197187
198188// NewSetWithSortable returns a new Set. See the documentation for
199189// NewSetWithSortableFiltered for more details.
200190//
201191// This call includes a Sortable option as a memory optimization.
202- func NewSetWithSortable (kvs []KeyValue , tmp * Sortable ) Set {
203- // Check for empty set.
204- if len (kvs ) == 0 {
205- return empty ()
206- }
207- s , _ := NewSetWithSortableFiltered (kvs , tmp , nil )
192+ //
193+ // Deprecated: Use [NewSet] instead.
194+ func NewSetWithSortable (kvs []KeyValue , _ * Sortable ) Set {
195+ s , _ := NewSetWithFiltered (kvs , nil )
208196 return s
209197}
210198
@@ -218,48 +206,12 @@ func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
218206 if len (kvs ) == 0 {
219207 return empty (), nil
220208 }
221- srt := sortables .Get ().(* Sortable )
222- s , filtered := NewSetWithSortableFiltered (kvs , srt , filter )
223- sortables .Put (srt )
224- return s , filtered
225- }
226-
227- // NewSetWithSortableFiltered returns a new Set.
228- //
229- // Duplicate keys are eliminated by taking the last value. This
230- // re-orders the input slice so that unique last-values are contiguous
231- // at the end of the slice.
232- //
233- // This ensures the following:
234- //
235- // - Last-value-wins semantics
236- // - Caller sees the reordering, but doesn't lose values
237- // - Repeated call preserve last-value wins.
238- //
239- // Note that methods are defined on Set, although this returns Set. Callers
240- // can avoid memory allocations by:
241- //
242- // - allocating a Sortable for use as a temporary in this method
243- // - allocating a Set for storing the return value of this constructor.
244- //
245- // The result maintains a cache of encoded attributes, by attribute.EncoderID.
246- // This value should not be copied after its first use.
247- //
248- // The second []KeyValue return value is a list of attributes that were
249- // excluded by the Filter (if non-nil).
250- func NewSetWithSortableFiltered (kvs []KeyValue , tmp * Sortable , filter Filter ) (Set , []KeyValue ) {
251- // Check for empty set.
252- if len (kvs ) == 0 {
253- return empty (), nil
254- }
255-
256- * tmp = kvs
257209
258210 // Stable sort so the following de-duplication can implement
259211 // last-value-wins semantics.
260- sort . Stable ( tmp )
261-
262- * tmp = nil
212+ slices . SortStableFunc ( kvs , func ( a , b KeyValue ) int {
213+ return cmp . Compare ( a . Key , b . Key )
214+ })
263215
264216 position := len (kvs ) - 1
265217 offset := position - 1
@@ -287,6 +239,35 @@ func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (S
287239 return Set {equivalent : computeDistinct (kvs )}, nil
288240}
289241
242+ // NewSetWithSortableFiltered returns a new Set.
243+ //
244+ // Duplicate keys are eliminated by taking the last value. This
245+ // re-orders the input slice so that unique last-values are contiguous
246+ // at the end of the slice.
247+ //
248+ // This ensures the following:
249+ //
250+ // - Last-value-wins semantics
251+ // - Caller sees the reordering, but doesn't lose values
252+ // - Repeated call preserve last-value wins.
253+ //
254+ // Note that methods are defined on Set, although this returns Set. Callers
255+ // can avoid memory allocations by:
256+ //
257+ // - allocating a Sortable for use as a temporary in this method
258+ // - allocating a Set for storing the return value of this constructor.
259+ //
260+ // The result maintains a cache of encoded attributes, by attribute.EncoderID.
261+ // This value should not be copied after its first use.
262+ //
263+ // The second []KeyValue return value is a list of attributes that were
264+ // excluded by the Filter (if non-nil).
265+ //
266+ // Deprecated: Use [NewSetWithFiltered] instead.
267+ func NewSetWithSortableFiltered (kvs []KeyValue , _ * Sortable , filter Filter ) (Set , []KeyValue ) {
268+ return NewSetWithFiltered (kvs , filter )
269+ }
270+
290271// filteredToFront filters slice in-place using keep function. All KeyValues that need to
291272// be removed are moved to the front. All KeyValues that need to be kept are
292273// moved (in-order) to the back. The index for the first KeyValue to be kept is
0 commit comments