[Wtr-development] [JIRA] Commented: (WTR-449) making Element#click_no_wait faster and easier debuggable

Jarmo Pertman (JIRA) watirjira at gmail.com
Tue Oct 19 16:14:20 EDT 2010


    [ http://jira.openqa.org/browse/WTR-449?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=19946#action_19946 ] 

Jarmo Pertman commented on WTR-449:
-----------------------------------

I realised now that rubygems is not actually needed in the spawned process as it was not before. It is possible to simplify the populating of $LOAD_PATH code a little and use watir-s libraries only.

I also realised that populating $LOAD_PATH with junk didn't add any extra time (at least not anything considerable) due to the fact that the files themselves were not actually loaded (see my comment above, which tried to state otherwise). So, in short - it still could be possible to remove the loading of rubygems and speed up #click_no_wait even more.

Adding this to my TODO-list :)

> making Element#click_no_wait faster and easier debuggable
> ---------------------------------------------------------
>
>                 Key: WTR-449
>                 URL: http://jira.openqa.org/browse/WTR-449
>             Project: Watir
>          Issue Type: Improvement
>          Components: HTML Controls
>    Affects Versions: 1.6.5
>         Environment: all environments
>            Reporter: Jarmo Pertman
>            Priority: Major
>
> I have been thinking of improving Element#click_no_wait for some time now. I can see the following problems with current solution:
> 1) code is not good - method _code_that_copies_readonly_array with funny comment in main namespace, eval_in_spawned_process with TODO and not-TODO comments
> 2) users have a lot of problems with click_no_wait (http://bit.ly/asirep) and current code doesn't allow easy debugging with monkey-patching or similar solutions
> 3) in the spawned process used for click_no_wait, no rubygems is loaded thus it's possible that users without having RUBYOPT set to -rubygems can't use click_no_wait and since it's hard to debug (see point #2) then they don't even know what's the problem
> 4) click_no_wait is just slow because it loads too many files/libraries in it's own process - it should just load all the necessary things and nothing else
> 5) currently, in the unit tests click_no_wait process doesn't use development libraries
> Here is a benchmark:
> *click_no_wait_bench.rb:*
> {noformat}
> require "rubygems"
> require "watir"
> require "benchmark"
> b = Watir::Browser.new
> b.goto "http://www.google.com"
> times = 5
> # almost original watir 1.6.5 code
> # * added gsub to avoid bug for some ruby versions
> # * using ruby instead of start rubyw to measure time
> module Watir
>   module PageContainer
>     def eval_in_spawned_process(command)
>       command.strip!
>       load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
>       ruby_code = "require 'watir/ie'; "
> #      ruby_code = "$HIDE_IE = #{$HIDE_IE};" # This prevents attaching to a window from setting it visible. However modal dialogs cannot be attached to when not visible.
>       ruby_code << "pc = #{attach_command}; " # pc = page container
>       # IDEA: consider changing this to not use instance_eval (it makes the code hard to understand)
>       ruby_code << "pc.instance_eval(#{command.inspect})"
>       exec_string = "ruby -e #{(load_path_code + '; ' + ruby_code).inspect}".gsub("\\\"", "'")
>       system(exec_string)
>     end
>   end
> end
> Benchmark.bmbm do |x|
>   x.report("watir 1.6.5") {times.times {b.button(:name => "btnG").click_no_wait}}
> end
> =begin
> Rehearsal -----------------------------------------------
> watir 1.6.5   0.031000   0.015000   0.046000 ( 26.136495)
> -------------------------------------- total: 0.046000sec
>                   user     system      total        real
> watir 1.6.5   0.000000   0.000000   0.000000 ( 23.600350)
> =end
> # improved section
> # * simplified click_no_wait methods
> # * requiring rubygems incase of missing RUBYOPT
> # * extracted ruby_execute_command into method for easier monkey-patching for debugging and testing reasons
> module Watir
>   class Element
>     def click_no_wait
>       assert_enabled
>       highlight(:set)
>       element = "#{self.class}.new(#{@page_container.attach_command}, :unique_number, #{self.unique_number})"
>       @page_container.click_no_wait(element)
>       highlight(:clear)
>     end
>   end
>   module PageContainer
>     def click_no_wait(element)
>       ruby_code = "require 'rubygems';" <<
>               "require 'watir/ie';" <<
>               "#{element}.click!"
>       system(spawned_click_no_wait_command(ruby_code))
>     end
>     def spawned_click_no_wait_command(command)
>       "start rubyw -e #{command.inspect}"
>     end
>     private :spawned_click_no_wait_command
>   end
> end
> Benchmark.bmbm do |x|
>   x.report("watir improved - ie") {times.times {b.button(:name => "btnG").click_no_wait}}
> end
> =begin
> Rehearsal -------------------------------------------------------
> watir improved - ie   0.032000   0.047000   0.079000 ( 20.141152)
> ---------------------------------------------- total: 0.079000sec
>                           user     system      total        real
> watir improved - ie   0.047000   0.016000   0.063000 ( 18.931083)
> =end
> # * loading watir/core.rb to reduce loading of unneeded files/libraries
> module Watir
>   class Element
>     def click_no_wait
>       assert_enabled
>       highlight(:set)
>       element = "#{self.class}.new(#{@page_container.attach_command}, :unique_number, #{self.unique_number})"
>       @page_container.click_no_wait(element)
>       highlight(:clear)
>     end
>   end
>   module PageContainer
>     def click_no_wait(element)
>       ruby_code = "require 'rubygems';" <<
>               "require '#{File.expand_path(File.dirname(__FILE__))}/watir/core';" <<
>               "#{element}.click!"
>       system(spawned_click_no_wait_command(ruby_code))
>     end
>     def spawned_click_no_wait_command(command)
>       unless $DEBUG
>         "start rubyw -e #{command.inspect}"
>       else
>         puts "#click_no_wait command:"
>         command = "ruby -e #{command.inspect}"
>         puts command
>         command
>       end
>     end
>     private :spawned_click_no_wait_command
>   end
> end
> Benchmark.bmbm do |x|
>   x.report("watir improved - click_no_wait") {times.times {b.button(:name => "btnG").click_no_wait}}
> end
> =begin
> Rehearsal ------------------------------------------------------------------
> watir improved - click_no_wait   0.062000   0.015000   0.077000 (  9.729557)
> --------------------------------------------------------- total: 0.077000sec
>                                      user     system      total        real
> watir improved - click_no_wait   0.015000   0.047000   0.062000 (  9.308532)
> =end
> b.close
> {noformat}
> *watir/core.rb:*
> {noformat}
> require 'watir/win32ole'
> require 'logger'
> require 'watir/exceptions'
> require 'watir/matches'
> require 'watir/core_ext'
> require 'watir/logger'
> require 'watir/container'
> require 'watir/locator'
> require 'watir/page-container'
> require 'watir/ie-class'
> require 'watir/element'
> require 'watir/element_collections'
> require 'watir/form'
> require 'watir/non_control_elements'
> require 'watir/input_elements'
> require 'watir/table'
> require 'watir/image'
> require 'watir/link'
> require 'watir/html_element'
> require 'watir/waiter'
> require 'watir/module'
> {noformat}
> As it's possible to see from the results then i got click_no_wait to perform faster about 2-3 times (of course this depends on the PC and so on, but these are the results from my machine, which is a quite average laptop)!
> Results:
> 1) removed all this unnecessary and funny-looking code which also had slight of a "criminal overengineering" smell on it (http://coderoom.wordpress.com/2010/06/23/criminal-overengineering/)
> 2) it is now easy to debug #click_no_wait problems:
> {noformat}
> $DEBUG = true
> element.click_no_wait
> {noformat}
> 3) requiring rubygems always, just in case, in the spawned process
> 4) click_no_wait performs 2-3x faster! It might be possible to improve the performance even more by doing some larger changes with the require statements in watir/core.rb - unfortunately it is not possible anymore to make changes in smaller steps
> 5) all click_no_wait invocations in unit tests use now development libraries
> Fixes are in branch click_no_wait_patch:
> http://github.com/jarmo/watir/tree/click_no_wait_patch

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.openqa.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the Wtr-development mailing list