Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Micro optimization:
[0...-3] = ''
is faster than slice!(-3, 3)
I noticed a surprising amount of allocations from this idiom: ``` Allocated String Report ----------------------------------- 109381 "" 13344 ~/gems/zeitwerk-2.2.2/lib/zeitwerk/loader.rb:479 ``` Turns out `slice!` allocates a wierd empty string for no reasons, as well as a string containing the sliced chars we don't care about: ```ruby >> s = "foo.rb"; MemoryProfiler.report { s.slice!(-3, 3) }.pretty_print Allocated String Report ----------------------------------- 1 "" 1 (irb):20 1 ".rb" 1 (irb):20 ``` Based on the context, I assume the `slice!` usage goal was to save some string allocations, but turns out it actually makes things worse. Two other candidate methods could be: - `byteslice`, as it ignore encoding it's marginally faster than `slice`. - `delete_suffix!` saves an allocation, but was introduced in Ruby 2.5. - `[]= ''` since that's what `slice!` end up doing internally. Benchmark: ```ruby require 'benchmark/ips' Benchmark.ips do |x| x.report('slice!(-3, 3)') { "foo.rb".slice!(-3, 3) } x.report('slice(0...-3)') { "foo.rb".slice(0...-3) } x.report('byteslice(0...-3)') { "foo.rb".byteslice(0...-3) } x.report('[-3..-1] = ""') { "foo.rb"[-3..-1] = ''.freeze } x.report('delete_suffix!') { "foo.rb".delete_suffix!(".rb".freeze) } end ``` ``` slice!(-3, 3) 4.939M (± 1.0%) i/s - 24.900M in 5.042534s slice(0...-3) 7.323M (± 1.4%) i/s - 36.774M in 5.023076s byteslice(0...-3) 8.126M (± 1.5%) i/s - 40.930M in 5.038314s [-3..-1] = "" 7.842M (± 0.7%) i/s - 39.249M in 5.005565s delete_suffix! 10.657M (± 5.8%) i/s - 53.283M in 5.025248s ```
- Loading branch information