Ruby "Speedup" hints?

Even in the 60’s computer scientists knew that:

“Premature optimization is the root of all evil.”

  • C. A. R. Hoare

Guys,

Given, we are talking about optimization, an big part of it is to
optimize
page-download times. I am told that this can be somewhat accomplished
using
the following -

  1. Strip spaces, tabs, CR/LF from the HTML
  2. Enable HTTP Compression

Is there a way in RoR w/ Mongrel to accomplish the two?

Rajat

On Tue, Mar 18, 2008 at 7:30 AM, Avdi G. [email protected] wrote:

JITing and other optimizations have made a lot of assumptions about
performance “truths” - to the point that the latter gains are lost in
gathered on.
Avdi


Rajat G.

Ph: 206-499-9495
Add: 1314 Spring Street, #412
Seattle, WA 98104
Web: http://www.pilotoutlook.com

Marc H. wrote:

(…)
If you know a few more hints, please add!

Date and DateTime are time consuming. Time however, is not.

require ‘benchmark’

N = 10000
Benchmark.bmbm do |bm|

bm.report ‘empty’ do
N.times do 1 end
end

bm.report ‘DateTime’ do
N.times {DateTime.new}
end

bm.report ‘Date’ do
N.times {Date.new}
end

bm.report ‘Time’ do
N.times {Time.new}
end

end

           user     system      total        real

empty 0.000000 0.000000 0.000000 ( 0.000000)
DateTime 3.687000 0.063000 3.750000 ( 3.813000)
Date 1.281000 0.000000 1.281000 ( 1.313000)
Time 0.016000 0.000000 0.016000 ( 0.015000)

Regards,

Siep

On 18 Mar 2008, at 05:40, Gerardo S. Gómez Garrido wrote:

I only have a few hints, like 5… would love to extend it.
Paul

output = StringIO.new
times.times { output.write(“hola mundo\n”) }
output.rewind
print output.read

The difference increases in real world reports.

Gerardo S.

Do you not realize that this is fundamentally telling you your
terminal is super-slow? This has nothing to do with ruby itself,
really. Try it on some other platforms and tool stacks, for goodness
sake.

And FYI, this is why context specific profiling is far more important
than any of these strange idioms you’re talking about.

Oh, and this is only really true for short strings and relatively
small amounts of memory. Try doing that whilst say, stream editing a
1TB file.

This whole direction of thought is broken, honestly.

On Tue, Mar 18, 2008 at 3:10 PM, Robert K.
[email protected] wrote:

Yes, that’s true. But I’m inclined to say that even in Java there is a
single operation that is always the most expensive (not counting IO of
course) and this is object creation.

In the embedded version of Java, where it is possible to pre-allocate
objects and object pools, even this may not be a reliable truism.

On Wed, Mar 19, 2008 at 10:25:32PM +0900, Paul B. wrote:

cout@bean:~/tmp$ time ruby c.rb 10_000_000 > /dev/null

real 0m13.141s
user 0m11.749s
sys 0m0.100s

The difference is even more stark on 1.9:

cout@bean:~/tmp$ time ruby1.9 a.rb 10_000_000 > /dev/null

real 0m48.103s
user 0m44.203s
sys 0m0.240s
cout@bean:~/tmp$ time ruby1.9 c.rb 10_000_000 > /dev/null

real 0m10.934s
user 0m10.425s
sys 0m0.076s

Paul

On Mar 19, 2008, at 9:29 AM, Paul B. wrote:

sys 0m0.504s
real 0m48.103s
user 0m44.203s
sys 0m0.240s
cout@bean:~/tmp$ time ruby1.9 c.rb 10_000_000 > /dev/null

real 0m10.934s
user 0m10.425s
sys 0m0.076s

Paul

OK, I avoided saying something on the previous message, but can you
(and anyone else who posts benchmarks like this) please use names
better than a.rb, b.rb, and c.rb so it actually makes some sense?
Particularly when quoted or forwarded!

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

On Wed, Mar 19, 2008 at 10:53:03PM +0900, Rob B. wrote:

OK, I avoided saying something on the previous message, but can you
(and anyone else who posts benchmarks like this) please use names
better than a.rb, b.rb, and c.rb so it actually makes some sense?
Particularly when quoted or forwarded!

I would normally do that, but I didn’t want to cause more confusion by
renaming the author’s original code.

Paul

On 3/19/08, James T. [email protected] wrote:

Anyone of you has a few hints on how to speed up ruby code?
Do you have a concrete example/benchmark that demonstrates the
real 1m45.305s
require ‘stringio’
Gerardo S.

Do you not realize that this is fundamentally telling you your
terminal is super-slow?
This has nothing to do with ruby itself,
really. Try it on some other platforms and tool stacks, for goodness
sake.

For goodness sake, read before replying. I’m not using any terminal.

Oh, and this is only really true for short strings and relatively
small amounts of memory. Try doing that whilst say, stream editing a
1TB file.

As I already said, this has proven true in real world reports.

This whole direction of thought is broken, honestly.

Fine. Don’t take the hint.

On 3/19/08, Paul B. [email protected] wrote:

sys 0m16.997s
print output.read

I think you are demonstrating the difference between IO#puts and
IO#write (which still surprised me).

Replace output.write(“hola mundo\n”) with output.puts(“hola mundo”)
and you’ll get something similar.

On Tue, Mar 18, 2008 at 02:40:43PM +0900, Gerardo S. G?mez Garrido
wrote:

$ cat a.rb
times = ARGV[0].to_i
times.times { puts “hola mundo” }
$ cat b.rb
require ‘stringio’

times = ARGV[0].to_i
output = StringIO.new
times.times { output.write(“hola mundo\n”) }
output.rewind
print output.read

I think you are demonstrating the difference between IO#puts and
IO#write (which still surprised me).

cout@bean:~/tmp$ time ruby a.rb 1_000_000 > /dev/null

real 0m2.769s
user 0m2.660s
sys 0m0.044s
cout@bean:~/tmp$ time ruby b.rb 1_000_000 > /dev/null

real 0m1.315s
user 0m1.244s
sys 0m0.020s
cout@bean:~/tmp$ time ruby c.rb 1_000_000 > /dev/null

real 0m1.256s
user 0m1.160s
sys 0m0.036s
cout@bean:~/tmp$ cat c.rb
times = ARGV[0].to_i
times.times { $stdout.write “hola mundo\n” }

And on my machine with 10_000_000 iterations I starting digging into
swap with
the stringio solution:

cout@bean:~/tmp$ time ruby a.rb 10_000_000 > /dev/null

real 0m27.841s
user 0m25.694s
sys 0m0.112s
cout@bean:~/tmp$ time ruby b.rb 10_000_000 > /dev/null

real 0m54.888s
user 0m11.333s
sys 0m0.504s
cout@bean:~/tmp$ time ruby c.rb 10_000_000 > /dev/null

real 0m13.141s
user 0m11.749s
sys 0m0.100s

Paul

On Thu, Mar 20, 2008 at 01:44:11AM +0900, Gerardo S. G?mez Garrido
wrote:

Replace output.write(“hola mundo\n”) with output.puts(“hola mundo”)
and you’ll get something similar.

Not much difference, and the StringIO solution uses more memory. Not
surprising, since both File#puts and StringIO#puts are implemented by
rb_io_puts.

The difference may be more dramatic on your platform, depending on the
implementation of your C library’s stdio functions.

[pbrannan@zaphod tmp]$ ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i686-linux]
[pbrannan@zaphod tmp]$ ruby test.rb
Rehearsal --------------------------------------------------
IO#puts 10.320000 0.010000 10.330000 ( 10.412573)
IO#write 5.110000 0.020000 5.130000 ( 5.171733)
StringIO#puts 9.740000 0.060000 9.800000 ( 9.847963)
StringIO#write 4.430000 0.040000 4.470000 ( 4.504434)
---------------------------------------- total: 29.730000sec

                 user     system      total        real

IO#puts 10.220000 0.010000 10.230000 ( 10.258458)
IO#write 5.090000 0.020000 5.110000 ( 5.164432)
StringIO#puts 10.150000 0.160000 10.310000 ( 10.438876)
StringIO#write 4.630000 0.090000 4.720000 ( 4.769139)
[pbrannan@zaphod tmp]$ cat test.rb
require ‘stringio’
require ‘benchmark’

Benchmark.bmbm(15) do |x|
devnull = File.open(’/dev/null’, ‘w’)
n = 2_000_000

x.report(“IO#puts”) {
n.times do
devnull.puts “hola”
end
}

x.report(“IO#write”) {
n.times do
devnull.write “hola\n”
end
}

x.report(“StringIO#puts”) {
s = StringIO.new
n.times do
s.puts “hola”
end
s.rewind
devnull.print s.read
}

x.report(“StringIO#write”) {
s = StringIO.new
n.times do
s.write “hola\n”
end
s.rewind
devnull.print s.read
}
end

2008/3/19, Paul B. [email protected]:

implementation of your C library’s stdio functions.
I’d say the difference is not worthwhile the added complexity and
memory overhead of StringIO:

18:35:19 /cygdrive/c/SCMws/
$ ruby <<XX

 end
 n.times do
 end
 s.rewind
 devnull.print s.read

}
end
end
XX
Rehearsal --------------------------------------------------
IO#puts 5.984000 0.016000 6.000000 ( 6.000000)
IO#write 2.875000 0.000000 2.875000 ( 2.885000)
StringIO#puts 4.219000 0.016000 4.235000 ( 4.240000)
StringIO#write 2.078000 0.031000 2.109000 ( 2.113000)
---------------------------------------- total: 15.219000sec

                 user     system      total        real

IO#puts 6.000000 0.000000 6.000000 ( 5.996000)
IO#write 2.875000 0.000000 2.875000 ( 2.871000)
StringIO#puts 4.203000 0.015000 4.218000 ( 4.224000)
StringIO#write 2.140000 0.047000 2.187000 ( 2.175000)
18:36:46 /cygdrive/c/SCMws/
$

Note: I added proper closing of devnull and made the stream binary.

Kind regards

robert

Oh, and this is only really true for short strings and relatively
small amounts of memory. Try doing that whilst say, stream editing a
1TB file.

As I already said, this has proven true in real world reports.

I’d be very impressed if you could afford the ram to do the
recommended trick with a 1TB file…

I’m not saying you can’t speed some things up using these methods, I’m
saying that any serious and sane requirement for performance will not
get significant gains from these kinds of suggestions, as this kind of
stuff is so rarely the real cause of performance loss.

It’s about how much indirection you have going on. Where and when does
puts clear buffers and so on?

This whole direction of thought is broken, honestly.

Fine. Don’t take the hint.

No worries, I can live with that. :slight_smile:

raggi@mbk:~/tmp/bench$ ruby runner.rb 10_000_000
time ruby a.rb 10000000 > /tmp/a

real 0m11.273s
user 0m10.042s
sys 0m0.483s
time ruby b.rb 10000000 > /tmp/b

real 0m7.473s
user 0m3.978s
sys 0m0.743s
time ruby c.rb 10000000 > /tmp/c

real 0m6.366s
user 0m5.403s
sys 0m0.491s
raggi@mbk:~/tmp/bench$ cat c.rb
times = ARGV[0].to_i
times.times { print “hola mundo\n” }

And the above will work with a significant sized stream, and bigger
sized strings. You’ll notice if you did bound check benchmarks, that
the other solutions have serious issues in various not uncommon bounds.

Whoops.