# Is String build faster than concatenation, or benchmarking wrong?

**URL:** <https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399>\
**Category:** Help & Support\
**Created:** [November 22, 2019, 6:07pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399 "2019-11-22T18:07:00Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacob](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jacob/32/615_2.png) [@jacob](https://forum.crystal-lang.org/u/jacob)\
**Post date:** [November 22, 2019, 6:07pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399/1 "2019-11-22T18:07:00Z")

</div>

I have learned like that, but my benchmarking code did not agree, is my code wrong?

```auto
require "benchmark"

Benchmark.ips do |x|
  x.report("build") do
    build_s
  end

  x.report("conc") do
    conc_s
  end
end

Benchmark.measure {
  10000.times do
    build_s
  end
}

Benchmark.bm do |x|
  x.report("build") do
    10000.times do
      build_s
    end
  end
end

def build_s
  String.build do |io|
    io << "foo" << 12
  end
end

def conc_s
  "foo" + 12.to_s
end

```

---

<div class="post-metadata">

**Author:** ![vlazar](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/vlazar/32/31_2.png) [@vlazar](https://forum.crystal-lang.org/u/vlazar)\
**Post date:** [November 22, 2019, 7:22pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399/2 "2019-11-22T19:22:17Z")

</div>

See related optimization in soon to be released Crystal 0.32.0 [https://github.com/crystal-lang/crystal/pull/8400](https://github.com/crystal-lang/crystal/pull/8400)

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [November 22, 2019, 8:10pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399/3 "2019-11-22T20:10:56Z")

</div>

Could you post your benchmark results? Otherwise we don’t know what you expect and what is the actual result.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [November 22, 2019, 8:22pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399/4 "2019-11-22T20:22:06Z")

</div>

In my case these are the results:

```auto
build 9.35M (106.91ns) (± 9.95%) 208B/op 2.97× slower
 conc 27.79M ( 35.99ns) (± 3.29%) 48.0B/op fastest

```

The reason `build` is slower is because `String.build` will create a `String::Builder` instance (memory allocated) and then allocate unknown size for what you are going to build (64 bytes at least) and then create a string out of it.

On the other hand `12.to_s` will allocate a string of exactly 2 bytes, then `"foo" + ...` will allocate a string of exactly 5 bytes.

Now that we’ll have `String.interpolation` in the next release we could add logic to optimize this. It’s a bit complex, but we could try to compute an effective size if all arguments to interpolate are strings or integers, and then use `String.new` instead of `String.build`.

---

<div class="post-metadata">

**Author:** ![jacob](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jacob/32/615_2.png) [@jacob](https://forum.crystal-lang.org/u/jacob)\
**Post date:** [November 23, 2019, 4:12pm UTC](https://forum.crystal-lang.org/t/is-string-build-faster-than-concatenation-or-benchmarking-wrong/1399/5 "2019-11-23T16:12:34Z")

</div>

Thanks for your explanation. The results are similar, I wonder this problem while I was reading “programming crystal”

> For efficiency, you should avoid creating extra strings. In the following snippet, both to\_s, +, and  
> string interpolation create a string on the heap, though interpolation is faster:

```
   rate = 0.84320536 
   p "rate: " + rate.to_s # => "rate: 0.84320536" 
   # string interpolation is more efficient: 
   p "rate: #{rate}" # => "rate: 0.84320536" 

```

> You can also use a String builder and the \<\< method:  
> str = String.build do |io|  
> io \<\< "rate: " \<\< rate  
> end  
> p str # =\> “rate: 0.84320536”

Thank you in advance.
