I just did a quick benchmark to prove something to myself. But I’d
like to get a sanity check from the people on the list.
Basically I want to drop what will be a trailing “\n” from input.
But it appears that using String#[] and if statements is nearly 200
times more efficient than chop. Which just seems really weird, so
here’s the benchmark. Maybe I’m doing something wrong.
Does this seem right? Anyone care to comment?
---- index_vs_chop.rb
require ‘benchmark’
n = 100_000
bigstring = "I am a big string " * 5_000
Benchmark.bmbm do |bench|
bench.report(“Indexing”) {
n.times do
bigstring[0…-1]
end
}
bench.report(“Chop”) {
n.times do
bigstring.chop
end
}
end
Basically I want to drop what will be a trailing “\n” from input.
But it appears that using String#[] and if statements is nearly 200
times more efficient than chop. Which just seems really weird, so
here’s the benchmark. Maybe I’m doing something wrong.
Well, if you implement chop fully, you get very similar results:
I just did a quick benchmark to prove something to myself. But I’d like
to get a sanity check from the people on the list.
Basically I want to drop what will be a trailing “\n” from input. But
it appears that using String#[] and if statements is nearly 200 times
more efficient than chop. Which just seems really weird, so here’s the
benchmark. Maybe I’m doing something wrong.
Does this seem right? Anyone care to comment?
As someone else pointed out, you’ll probably want to use String#chop!
for
faster performance, since it uses the current object instead of creating
a new one.
Also note that str[0…-2] is not quite the same as str.chop when “\r\n”
is
involved:
I wouldn’t think the extra work of checking for “\r\n” would add that
much
overhead, though.
Regards,
Dan
This communication is the property of Qwest and may contain confidential
or
privileged information. Unauthorized use of this communication is
strictly
prohibited and may be unlawful. If you have received this communication
in error, please immediately notify the sender by reply e-mail and
destroy
all copies of the communication and any attachments.
Basically I want to drop what will be a trailing “\n” from input.
But it appears that using String#[] and if statements is nearly
200 times more efficient than chop. Which just seems really
weird, so here’s the benchmark. Maybe I’m doing something wrong.
Well, if you implement chop fully, you get very similar results:
Ah, but rangeless indexing yields much much better results:
I just did a quick benchmark to prove something to myself. But I’d
like to get a sanity check from the people on the list.
[snip]
Benchmark.bmbm do |bench|
bench.report(“Indexing”) {
n.times do
bigstring[0…-1]
end
}
[snip]
No-one seems to have noticed the typo…? I think that 4th line should
be:
bigstring[0…-2]
Which is slower. That should account for part of the performance gap.
I think the difference in performance is because internally chop does
a dup on the string then calls chop! whereas the index operation
creates a new string which shares the old string but with a different
length. I guess this is also why the rehearsal and final results
differ - cutting out the cost of GC doesn’t reflect the true cost of
using chop (especially with big strings).
Ah, but rangeless indexing yields much much better results:
Speaking of catching typos, I apparently went too happy with my de-
ranging and implemented the wrong thing. Here are the actual results.
Pretty much the same as with ranges:
---------------------------------- total: 21.562000sec
a dup on the string then calls chop! whereas the index operation
creates a new string which shares the old string but with a different
length. I guess this is also why the rehearsal and final results
differ - cutting out the cost of GC doesn’t reflect the true cost of
using chop (especially with big strings).
Regards,
Sean
Indexing allocates a new string. It has to since (1) Ruby strings are
mutable, (2) Ruby strings have \0 at the end.