[
http://jira.openqa.org/browse/WTR-449?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Jarmo Pertman resolved WTR-449.
-------------------------------
Resolution: Fixed
merged into master
> 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
_______________________________________________
Wtr-development mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/wtr-development