[
http://jira.openqa.org/browse/WTR-449?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=19730#action_19730
]
Jarmo Pertman commented on WTR-449:
-----------------------------------
I forgot to add a comment to the benchmark test that this test was more of a
less ideal scenario. In the real world you would probably have loaded tons of
other libraries as well in your tests like maybe ActiveRecord and ActiveSupport
and so on. What this currently means is that current implementation of
#click_no_wait also loads these libraries (!!!) - method
_code_that_copies_readonly_array is to blame. But these libraries are
never-ever-never-ever needed when performing #click_no_wait. I couldn't think
of any case where any external file or library might be needed for
#click_no_wait. I guess the reason being that there isn't any case (prove if
i'm wrong). Only case when something like this might be needed would be a
situation where #click_no_wait itself is monkey-patched - but then again the
method for spawning the process might be also monkey-patched so no problems
there also.
So, if you have ActiveRecord or ActiveSupport loaded and you perform
#click_no_wait you'll lose another ~2 seconds:
irb(main):001:0> t = Time.now; require 'activerecord'; puts Time.now - t
2.039117
irb(main):001:0> t = Time.now; require 'active_support'; puts Time.now - t
2.122121
Now add it up for every #click_no_wait and you'll understand how much time is
lost for absolutely nothing :)
> 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 'watir/core';" <<
> "#{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 - 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 modest laptop)!
> I call this as a quite big improvement if we think about all the Web 2.0
> websites where #click_no_wait is often used.
> 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 debuggable, just use this monkey-patch:
> {noformat}
> Watir::PageContainer.class_eval {def spawned_click_no_wait_command(command)
> "ruby -e #{command.inspect}" end}
> {noformat}
> Maybe make it even more easier by using $DEBUG and if-statement or something
> similar?
> 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 within commits:
> http://github.com/jarmo/watir/commit/7333081e30568ec73eb63f9f75562c2078c55481
> http://github.com/jarmo/watir/commit/c71cee1ac820493372d299b8f3a258b497b22e66
--
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