On 01 Jun 2005, at 18:36, Gyoung-Yoon Noh wrote:
> OK, you're right in case of String#gsub and String#gsub!.
> But not 'a lot slower' but 'a little slower'.
>
> $ cat destructive.rb
> require 'benchmark'
>
> Benchmark.bmbm do |bm|
> bm.report("Destructive") do
> 100.times do
> str = (0..10000).to_a.join('-')
> str.gsub!(/\d+/, '-')
> end
> end
> bm.report("Non-destructive") do
> 100.times do
> str = (0..10000).to_a.join('-')
> str = str.gsub(/\d+/, '-')
> end
> end
> end
>
> $ ruby destructive.rb
> Rehearsal ---------------------------------------------------
> Destructive 4.240000 0.010000 4.250000 ( 4.448997)
> Non-destructive 4.250000 0.010000 4.260000 ( 4.279959)
> ------------------------------------------ total: 8.510000sec
>
> user system total real
> Destructive 4.260000 0.010000 4.270000 ( 4.378810)
> Non-destructive 4.230000 0.010000 4.240000 ( 4.305321)
The difference is not in the speed of the operations themselves, it
is in the memory pressure on the GC. Your benchmark is not a fair
comparison between the two because it ignores the side-effect of
memory pressure and does not fit with the way you would use chaining
vs !.
This benchmark more realisticly shows the effects of memory pressure
and is more fitting with how you would really use chaining vs !:
$ cat sub.rb
require 'benchmark'
N = 10_000
STR = (0..N).to_a.join('-')
Benchmark.bmbm do |bm|
bm.report("Base") do
str = STR.dup
N.times { }
end
bm.report("Destructive") do
str = STR.dup
N.times { str.sub!(/\d+/, '-') }
end
bm.report("Non-destructive") do
str = STR.dup
N.times { str = str.sub(/\d+/, '-') }
end
end
$ ruby sub.rb
Rehearsal ---------------------------------------------------
Base 0.000000 0.000000 0.000000 ( 0.003034)
Destructive 1.470000 1.380000 2.850000 ( 3.266492)
Non-destructive 1.930000 2.740000 4.670000 ( 5.584387)
------------------------------------------ total: 7.520000sec
user system total real
Base 0.000000 0.000000 0.000000 ( 0.002857)
Destructive 1.460000 1.400000 2.860000 ( 3.383933)
Non-destructive 1.910000 2.800000 4.710000 ( 5.688635)
> I don't understand what exactly this difference implies.
Your benchmark wasn't helpful in revealing the true difference
between the two methods. As you can see, the non-destructive case
takes much more time in user space because the GC has to clean up all
the temporary strings.
It also takes ~33% more time in general because of the GC.
> Does that mean Ruby's String is much alike raw C string?
It wraps a C string.
> Or is there any particular optimization for String copy?
Certain operations are COW.
--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04