From 1527ed8246c55dc23b261831d15f5434b2aaf914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rebughini?= Date: Tue, 28 Mar 2023 10:06:56 +0200 Subject: [PATCH] Introduce a specialised helper to return frozen dups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the Datadog::Tracing::Correlation::Identifier the unfrozen copies of strings are then frozen again: that's a step that can be skipped if the original value is already frozen, so we can save allocations. require "bundler/inline" gemfile(true) do source "https://rubygems.org" gem "benchmark-ips" gem "benchmark-memory" end Benchmark.ips do |x| x.report("+(-@).freeze") { v = "foo"; c = +(-v).freeze } x.report("-v") { v = "foo"; c = -v } x.compare! end Benchmark.memory do |x| x.report("+(-@).freeze") { v = "foo"; c = +(-v).freeze } x.report("-v") { v = "foo"; c = -v } x.compare! end Warming up -------------------------------------- +(-@).freeze 691.075k i/100ms -v 886.370k i/100ms Calculating ------------------------------------- +(-@).freeze 6.965M (± 0.5%) i/s - 35.245M in 5.060545s -v 8.839M (± 0.6%) i/s - 44.318M in 5.014288s Comparison: -v: 8838792.7 i/s +(-@).freeze: 6964819.0 i/s - 1.27x slower Calculating ------------------------------------- +(-@).freeze 80.000 memsize ( 0.000 retained) 2.000 objects ( 0.000 retained) 1.000 strings ( 0.000 retained) -v 40.000 memsize ( 0.000 retained) 1.000 objects ( 0.000 retained) 1.000 strings ( 0.000 retained) Comparison: -v: 40 allocated +(-@).freeze: 80 allocated - 2.00x more --- lib/datadog/core/utils/safe_dup.rb | 8 ++++++++ lib/datadog/tracing/correlation.rb | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/datadog/core/utils/safe_dup.rb b/lib/datadog/core/utils/safe_dup.rb index d0c064c76d4..33d20c11998 100644 --- a/lib/datadog/core/utils/safe_dup.rb +++ b/lib/datadog/core/utils/safe_dup.rb @@ -24,10 +24,18 @@ def self.frozen_or_dup(v) # - then it will dup it more efficiently with +v v.frozen? ? v : +(-v) end + + def self.frozen_dup(v) + -v if v + end else def self.frozen_or_dup(v) v.frozen? ? v : v.dup end + + def self.frozen_dup(v) + v.frozen? ? v : v.dup.freeze + end end end end diff --git a/lib/datadog/tracing/correlation.rb b/lib/datadog/tracing/correlation.rb index 65dde53bf10..67d5a12ca84 100644 --- a/lib/datadog/tracing/correlation.rb +++ b/lib/datadog/tracing/correlation.rb @@ -46,18 +46,18 @@ def initialize( version: nil ) # Dup and freeze strings so they aren't modified by reference. - @env = Core::Utils::SafeDup.frozen_or_dup(env || Datadog.configuration.env).freeze - @service = Core::Utils::SafeDup.frozen_or_dup(service || Datadog.configuration.service).freeze + @env = Core::Utils::SafeDup.frozen_dup(env || Datadog.configuration.env) + @service = Core::Utils::SafeDup.frozen_dup(service || Datadog.configuration.service) @span_id = span_id || 0 - @span_name = Core::Utils::SafeDup.frozen_or_dup(span_name).freeze - @span_resource = Core::Utils::SafeDup.frozen_or_dup(span_resource).freeze - @span_service = Core::Utils::SafeDup.frozen_or_dup(span_service).freeze - @span_type = Core::Utils::SafeDup.frozen_or_dup(span_type).freeze + @span_name = Core::Utils::SafeDup.frozen_dup(span_name) + @span_resource = Core::Utils::SafeDup.frozen_dup(span_resource) + @span_service = Core::Utils::SafeDup.frozen_dup(span_service) + @span_type = Core::Utils::SafeDup.frozen_dup(span_type) @trace_id = trace_id || 0 - @trace_name = Core::Utils::SafeDup.frozen_or_dup(trace_name).freeze - @trace_resource = Core::Utils::SafeDup.frozen_or_dup(trace_resource).freeze - @trace_service = Core::Utils::SafeDup.frozen_or_dup(trace_service).freeze - @version = Core::Utils::SafeDup.frozen_or_dup(version || Datadog.configuration.version).freeze + @trace_name = Core::Utils::SafeDup.frozen_dup(trace_name) + @trace_resource = Core::Utils::SafeDup.frozen_dup(trace_resource) + @trace_service = Core::Utils::SafeDup.frozen_dup(trace_service) + @version = Core::Utils::SafeDup.frozen_dup(version || Datadog.configuration.version) end def to_log_format