Nagoya RubyKaigi 02




How to Make
Ruby CGI Script Faster
CGI


makoto kuwata
http://www.kuwata-lab.com/
What I'll talk and not
 I talk about            I don't talk about

   Why CGI is so slow?     Scale out

   How to improve your     Database
   code?
                           Key Value Store

                           Or other kool topics
Why CGI Script
is So Slow?
Example Code
               	           }
       	  	 
                                }


                                            }
Benchmark
  Process Invocation         require 'cgi'
  cgi = CGI.new              render HTML

                1.80%
               0.87%

                        39.55%

          57.78%
                                    Mac OS X 10.6
                                    Ruby 1.8.7-p334
                                    Core2 Duo 2GHz

                             https://gist.github.com/850390
Why CGI is so slow?
 FACT
  Process invocation is slow


 TRUTH
  Library loading is much slow
Benchmark of 'require'
           (none)         6.15                 1.8.7-p334
               erb           9.26
             time                   15.9          Library loading
                uri                 16.15         is much slower
         fileutils                    17.26        than process
               cgi                   17.31        invocation
          tmpdir                     17.84
                                                (
          pstore                       19.19
            date2                      19.4                      )
        openssl                          21.92
        tempfile                           22.53
    cgi/session                                  30.18
             yaml                                  32.27
rexml/document                                           40.96
                      0     10        20      30           40        50 (ms)
                                             https://gist.github.com/850386
Benchmark of 'require'
           (none)     13.35                  1.9.2-p180
               erb       21.58
             time           30.88
                uri              43.42
         fileutils              37.52
               cgi        25.82
          tmpdir               39.07
          pstore                   48.8
            date2 0
        openssl               36.16
        tempfile                       53.82
    cgi/session                        57.38
             yaml                                81.61
rexml/document                                                109.42
                 0     20     40      60       80       100      120 (ms)
                                           https://gist.github.com/850386
Benchmark of 'require'
           (none)                          1.8.7-p334
               erb                         1.9.2-p180
             time
                uri                      1.9 is slower than
         fileutils                        1.8 for process
               cgi                       invocation and
          tmpdir                         library loading
          pstore                         (1.9
            date2
        openssl                          1.8                 )
        tempfile
    cgi/session
             yaml
rexml/document
                      0   20   40   60          80   100   120 (ms)
Case Study: tmpdir
 tmpdir.rb requires fileutils.rb
 tmpdir.rb fileutils.rb   require
Case Study: tmpdir
 Change to require only when necessary
                        require
Benchmark
                before           after




                                  17.84

tmpdir.rb
                     6.99


            0        5      10   15       20   (ms)
Case Study: delegate
 DelegateClass makes library loading slow
 DelegateClass
Benchmark
                 Using DelegateClass
                 Without DelegateClass


                              17.31
    cgi.rb
                          14.17


                                       22.53
tempfile.rb
                                   19.29

             0     5     10       15       20   25   (ms)
Case Study: openssl
 Openssl pollutes other libraries
 openssl                      require
Case Study: openssl
 Calculate session id without
 securerandom.rb
 securerandom.rb                      ID
How to Improve
Your Code?
How to improve?
Answer
Benchmark
                                      h() is much slower than
              h(s1)                  escape_html() when there
    escape_html(s1)                    are '&<>"' characters
                                     (   &<>"               escape_html()
              h(s2)                       h()                     )
    escape_html(s2)

              h(s3)
    escape_html(s3)
                          0   12.5         25        37.5           50
s1 : 0 html characters                                      Ruby 1.8.7-p334

s2 : 5 html characters
s3 : 15 html characters                     https://gist.github.com/850396
How to improve?
Answer
Answer
      	 
	 	         	  	 
	 	                                        	      	 
	 	 	 	     	       	  	                            	 
	 	 	 	    	  	                              	      	    	    	 
	 	 	 	    	  	 
	 	 	 	                     	    	    	    	 
	 	                                               Ignore '+' :)
Benchmark
                   Ruby 1.8.7-p334

parse1()
parse2()
parse3()
           0   2          4          6           8


                   Ruby 1.9.2-p180

parse1()
parse2()
parse3()
           0   2          4          6           8
                                     https://gist.github.com/850402
How to improve?
Answer
Example Code
Benchmark
                   Ruby 1.8.7-p334

parse_nested_query()

parse_dotted_query()
                       0    3.5         7         10.5        14


                   Ruby 1.9.2-p180

parse_nested_query()

parse_dotted_query()
                       0    3.5         7         10.5        14
                                     https://gist.github.com/850407
How to improve?
      	  	 
             	  	 
           	  	          	  	 
                              	    	      	 
	 	           	  	  	 
	 	 	 	 
	 	                                     renaming is faster
                                         than read&write
                                    (
                                                   rename
                                                       )
Answer                                    Moving file on other
                                        partition is too expensive
                                        (
       	  	                                                      )
Answer
                         	  	 
                	 
      	  	 
              	  	 
         	 
	 	 	         	 

                      Set $TMPDIR before loading cgi.rb
                      (require 'cgi'
                                                )
How to improve?
     	                               	 
	 	          	  	  	 
	 	 	 	         	  	     	 
	 	 	 	 	 	 

                    C/Java style coding is slow in Ruby
                    (C    Java                         ,
                         Ruby                      )
Answer
Conslusion
Ruby
There are a lot of code which is not so
efficent
(                     )


If your code is slow, it is due to yourself,
not to Ruby.
(
Ruby           )
one more thing...
Benchmarker
 Benchmarker
  Benchmark utility
  Repeat benchmarks, average results, ...
CGIAlt, CGIExt
 CGIAlt
  Fast and cgi.rb compatible
  http://cgialt.rubyforge.org/

 CGIExt
  Implemented in C
  http://cgiext.rubyforge.org/
thank you

How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -

  • 1.
    Nagoya RubyKaigi 02 Howto Make Ruby CGI Script Faster CGI makoto kuwata http://www.kuwata-lab.com/
  • 2.
    What I'll talkand not I talk about I don't talk about Why CGI is so slow? Scale out How to improve your Database code? Key Value Store Or other kool topics
  • 3.
  • 4.
  • 5.
    Benchmark ProcessInvocation require 'cgi' cgi = CGI.new render HTML 1.80% 0.87% 39.55% 57.78% Mac OS X 10.6 Ruby 1.8.7-p334 Core2 Duo 2GHz https://gist.github.com/850390
  • 6.
    Why CGI isso slow? FACT Process invocation is slow TRUTH Library loading is much slow
  • 7.
    Benchmark of 'require' (none) 6.15 1.8.7-p334 erb 9.26 time 15.9 Library loading uri 16.15 is much slower fileutils 17.26 than process cgi 17.31 invocation tmpdir 17.84 ( pstore 19.19 date2 19.4 ) openssl 21.92 tempfile 22.53 cgi/session 30.18 yaml 32.27 rexml/document 40.96 0 10 20 30 40 50 (ms) https://gist.github.com/850386
  • 8.
    Benchmark of 'require' (none) 13.35 1.9.2-p180 erb 21.58 time 30.88 uri 43.42 fileutils 37.52 cgi 25.82 tmpdir 39.07 pstore 48.8 date2 0 openssl 36.16 tempfile 53.82 cgi/session 57.38 yaml 81.61 rexml/document 109.42 0 20 40 60 80 100 120 (ms) https://gist.github.com/850386
  • 9.
    Benchmark of 'require' (none) 1.8.7-p334 erb 1.9.2-p180 time uri 1.9 is slower than fileutils 1.8 for process cgi invocation and tmpdir library loading pstore (1.9 date2 openssl 1.8 ) tempfile cgi/session yaml rexml/document 0 20 40 60 80 100 120 (ms)
  • 10.
    Case Study: tmpdir tmpdir.rb requires fileutils.rb tmpdir.rb fileutils.rb require
  • 11.
    Case Study: tmpdir Change to require only when necessary require
  • 12.
    Benchmark before after 17.84 tmpdir.rb 6.99 0 5 10 15 20 (ms)
  • 13.
    Case Study: delegate DelegateClass makes library loading slow DelegateClass
  • 14.
    Benchmark Using DelegateClass Without DelegateClass 17.31 cgi.rb 14.17 22.53 tempfile.rb 19.29 0 5 10 15 20 25 (ms)
  • 15.
    Case Study: openssl Openssl pollutes other libraries openssl require
  • 16.
    Case Study: openssl Calculate session id without securerandom.rb securerandom.rb ID
  • 17.
  • 18.
  • 19.
  • 20.
    Benchmark h() is much slower than h(s1) escape_html() when there escape_html(s1) are '&<>"' characters ( &<>" escape_html() h(s2) h() ) escape_html(s2) h(s3) escape_html(s3) 0 12.5 25 37.5 50 s1 : 0 html characters Ruby 1.8.7-p334 s2 : 5 html characters s3 : 15 html characters https://gist.github.com/850396
  • 21.
  • 22.
  • 23.
    Answer Ignore '+' :)
  • 24.
    Benchmark Ruby 1.8.7-p334 parse1() parse2() parse3() 0 2 4 6 8 Ruby 1.9.2-p180 parse1() parse2() parse3() 0 2 4 6 8 https://gist.github.com/850402
  • 25.
  • 26.
  • 27.
  • 28.
    Benchmark Ruby 1.8.7-p334 parse_nested_query() parse_dotted_query() 0 3.5 7 10.5 14 Ruby 1.9.2-p180 parse_nested_query() parse_dotted_query() 0 3.5 7 10.5 14 https://gist.github.com/850407
  • 29.
    How to improve? renaming is faster than read&write ( rename )
  • 30.
    Answer Moving file on other partition is too expensive ( )
  • 31.
    Answer Set $TMPDIR before loading cgi.rb (require 'cgi' )
  • 32.
    How to improve? C/Java style coding is slow in Ruby (C Java , Ruby )
  • 33.
  • 34.
  • 35.
    Ruby There are alot of code which is not so efficent ( ) If your code is slow, it is due to yourself, not to Ruby. ( Ruby )
  • 36.
  • 37.
    Benchmarker Benchmarker Benchmark utility Repeat benchmarks, average results, ...
  • 38.
    CGIAlt, CGIExt CGIAlt Fast and cgi.rb compatible http://cgialt.rubyforge.org/ CGIExt Implemented in C http://cgiext.rubyforge.org/
  • 39.