Last active
July 12, 2021 07:13
-
-
Save postmodern/b664b4a34ea7c1f2598cde04cb5bff5b to your computer and use it in GitHub Desktop.
Ruby String building benchmarks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'benchmark' | |
require 'zlib' | |
Benchmark.bm(12) do |b| | |
n = 10_009_000 | |
str1 = 'A' | |
str2 = 'A' | |
str3 = 'A' | |
str4 = 'A' | |
str5 = 'A' | |
str6 = 'A' | |
str7 = 'A' | |
str8 = 'A' | |
str9 = 'A' | |
str10 = 'A' | |
b.report('interpolated') do | |
n.times do | |
"#{str1} #{str2} #{str3} #{str4} #{str5} #{str6} #{str7} #{str8} #{str9} #{str10}" | |
end | |
end | |
b.report('String#<<') do | |
n.times do | |
buffer = String.new('', capacity: 19) | |
buffer << str1 << ' ' << str2 << ' ' << str3 << ' ' << str4 << ' ' << str5 << ' ' << str6 << ' ' << str7 << ' ' << str8 << ' ' << str9 << ' ' << str10 | |
end | |
end | |
b.report('String#[]=') do | |
n.times do | |
buffer = ' ' * 19 | |
buffer[0,1] = str1 | |
buffer[1,1] = str2 | |
buffer[2,1] = str3 | |
buffer[3,1] = str4 | |
buffer[4,1] = str5 | |
buffer[5,1] = str6 | |
buffer[6,1] = str7 | |
buffer[7,1] = str8 | |
buffer[8,1] = str9 | |
buffer[9,1] = str10 | |
end | |
end | |
b.report('Array#join') do | |
n.times do | |
[str1, str2, str3, str4, str5, str6, str7, str8, str9, str10].join(' ') | |
end | |
end | |
end |
and the results of running the benchmarks under benchmark-ips.
Warming up --------------------------------------
interpolated 1.000 i/100ms
String#<< 1.000 i/100ms
String#[]= 1.000 i/100ms
Array#join 1.000 i/100ms
Calculating -------------------------------------
interpolated 0.109 (± 0.0%) i/s - 1.000 in 9.209206s
String#<< 0.045 (± 0.0%) i/s - 1.000 in 22.043854s
String#[]= 0.076 (± 0.0%) i/s - 1.000 in 13.169221s
Array#join 0.071 (± 0.0%) i/s - 1.000 in 14.087317s
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting!
If you have this code:
"a #{b} c"
and see what bytecode Ruby produces for it:
You get this:
So it pushes strings to the VM stack, then executes the
concatstrings
instruction, which is defined here:https://github.com/ruby/ruby/blob/c2ed5ab08b0f508185b4abd2d28f045616e7c7f5/insns.def#L372-L383
It's still strange that
String.new
combined with#<<
is much slower, maybe<<
does some checks to see the types, or something like that.