Skip to content

Commit

Permalink
Use @+ instead of dup for duplicating strings on supported Rubies
Browse files Browse the repository at this point in the history
String#+@ was introduced in Ruby 2.3: it is faster and a bit cheaper on
the memory side as well than #dup.

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "benchmark-ips"
  gem "benchmark-memory"
end

Benchmark.ips do |x|
  x.report("dup") { "foo".dup }
  x.report("@+") { +"foo" }

  x.compare!
end

Benchmark.memory do |x|
  x.report("dup") { "foo".dup }
  x.report("@+") { +"foo" }

  x.compare!
end

Warming up --------------------------------------
                  dup   642.978k i/100ms
                  @+     1.350M i/100ms
Calculating -------------------------------------
                  dup      6.646M (± 0.6%) i/s -     33.435M in   5.030737s
                  @+     13.503M (± 0.7%) i/s -     67.515M in   5.000186s

Comparison:
                  @+: 13503099.2 i/s
                  dup:  6646345.1 i/s - 2.03x  slower

Calculating -------------------------------------
                  dup    80.000  memsize (     0.000  retained)
                          2.000  objects (     0.000  retained)
                          1.000  strings (     0.000  retained)
                  @+    40.000  memsize (     0.000  retained)
                          1.000  objects (     0.000  retained)
                          1.000  strings (     0.000  retained)

Comparison:
                  @+:         40 allocated
                  dup:         80 allocated - 2.00x more
  • Loading branch information
nirebu committed Mar 26, 2023
1 parent 1720689 commit eb2d638
Showing 1 changed file with 9 additions and 2 deletions.
11 changes: 9 additions & 2 deletions lib/datadog/core/utils/safe_dup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ def dup
using RefineNil
end

def self.frozen_or_dup(v)
v.frozen? ? v : v.dup
# String#+@ was introduced in Ruby 2.3
if String.method_defined?(:+@)
def self.frozen_or_dup(v)
v.frozen? ? v : +v
end
else
def self.frozen_or_dup(v)
v.frozen? ? v : v.dup
end
end
end
end
Expand Down

0 comments on commit eb2d638

Please sign in to comment.