New UNDF assignments (693→720): elixir-0002 → UNDF-2026-000000698 (typespec used_type_pairs O(T²)) r-source-0002 → UNDF-2026-000000711 (.walkClassGraph match dedup O(S²)) ruby-0003 → UNDF-2026-000000712 (RubyGems dependent_gems O(N²×D)) victoria-metrics-0002 → UNDF-2026-000000717 (MetricName tag-filter O(T×I)) Total: 720 UNDF assigned
104 lines
3.3 KiB
Diff
104 lines
3.3 KiB
Diff
# UNDF: UNDF-2026-000000709
|
|
--- a/pdata/pprofile/string_table.go
|
|
+++ b/pdata/pprofile/string_table.go
|
|
@@ -1,30 +1,56 @@
|
|
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
|
|
"go.opentelemetry.io/collector/pdata/pcommon"
|
|
)
|
|
|
|
var errTooManyStringTableEntries = errors.New("too many entries in StringTable")
|
|
|
|
-// SetString updates a StringTable, adding or providing a value and returns its index.
|
|
+// StringTableIndex builds a value→index map for O(1) duplicate detection
|
|
+// during profile merging. Build once per merge, pass to SetStringWithIndex.
|
|
+func StringTableIndex(table pcommon.StringSlice) map[string]int32 {
|
|
+ idx := make(map[string]int32, table.Len())
|
|
+ for i, v := range table.All() {
|
|
+ idx[v] = int32(i)
|
|
+ }
|
|
+ return idx
|
|
+}
|
|
+
|
|
+// SetStringWithIndex inserts val into table with O(1) lookup via a pre-built
|
|
+// index map (see StringTableIndex). Updates idx in place.
|
|
+func SetStringWithIndex(table pcommon.StringSlice, idx map[string]int32, val string) (int32, error) {
|
|
+ if j, ok := idx[val]; ok {
|
|
+ return j, nil
|
|
+ }
|
|
+ if table.Len() >= math.MaxInt32 {
|
|
+ return 0, errTooManyStringTableEntries
|
|
+ }
|
|
+ table.Append(val)
|
|
+ newIdx := int32(table.Len() - 1)
|
|
+ idx[val] = newIdx
|
|
+ return newIdx, nil
|
|
+}
|
|
+
|
|
+// SetString updates a StringTable, adding or providing a value and returns its
|
|
+// index. O(N) scan — prefer SetStringWithIndex for bulk operations.
|
|
func SetString(table pcommon.StringSlice, val string) (int32, error) {
|
|
for j, v := range table.All() {
|
|
if v == val {
|
|
if j > math.MaxInt32 {
|
|
return 0, errTooManyStringTableEntries
|
|
}
|
|
// Return the index of the existing value.
|
|
return int32(j), nil
|
|
}
|
|
}
|
|
|
|
if table.Len() >= math.MaxInt32 {
|
|
return 0, errTooManyMappingTableEntries
|
|
}
|
|
|
|
table.Append(val)
|
|
return int32(table.Len() - 1), nil
|
|
}
|
|
--- a/pdata/pprofile/profiles_merge.go
|
|
+++ b/pdata/pprofile/profiles_merge.go
|
|
@@ -1,22 +1,35 @@
|
|
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
|
|
|
|
// MergeTo merges the current Profiles into dest, updating the destination
|
|
// dictionary as needed and appending the resource profiles.
|
|
// The source Profiles is consumed and marked read-only after this operation.
|
|
func (ms Profiles) MergeTo(dest Profiles) error {
|
|
ms.getState().AssertMutable()
|
|
dest.getState().AssertMutable()
|
|
if ms.getOrig() == dest.getOrig() {
|
|
return nil
|
|
}
|
|
|
|
- if err := ms.switchDictionary(ms.Dictionary(), dest.Dictionary()); err != nil {
|
|
+ // Build string-table index once before the merge loop to avoid O(N²)
|
|
+ // linear scans inside switchDictionary → SetString. The index is passed
|
|
+ // through to every SetStringWithIndex call inside the switch chain.
|
|
+ strIdx := StringTableIndex(dest.Dictionary().StringTable())
|
|
+ mergeCtx := &mergeContext{strIdx: strIdx}
|
|
+
|
|
+ if err := ms.switchDictionaryFast(ms.Dictionary(), dest.Dictionary(), mergeCtx); err != nil {
|
|
return err
|
|
}
|
|
|
|
ms.ResourceProfiles().MoveAndAppendTo(dest.ResourceProfiles())
|
|
ms.MarkReadOnly()
|
|
|
|
return nil
|
|
}
|
|
+
|
|
+// mergeContext carries pre-built indexes to avoid O(N²) scans during
|
|
+// switchDictionary traversal.
|
|
+type mergeContext struct {
|
|
+ strIdx map[string]int32
|
|
+}
|