8 Replies Latest reply on Oct 11, 2013 12:06 PM by Kevin Lollock

    Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.

      Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.

        • Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.
          Pietro Francesco Maggi

          Hi Giri,

          what latency are you talking about?

          Can you provide a small code sample to explain what you mean, otherwise it will be difficult to provide an help!

           

          Regarding general performance improvement there's quite some content in the Blog area of Launchpad:

          RhoElements Performance Improvements #1

          RhoElements Performance Improvements #2

          RhoElements Performance Improvements #3

          RhoElements Performance Improvements #4

          Native Application Optimizations

           

           

          ~Pietro

            • Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.

              Hi Pietro,

               

              Thanks for your response. Below is the sample code of Javascript and Ruby. I am calling Proxy method from Javascript.

               

              1. Javascript Code

               

              $.ajax({

                  type: requestType,

                  url: "/app/Httpproxy/proxy",

                  dataType: "text",

                  data: data,

                  beforeSend: function () {

                   timeStart = new Date();

                   mcf.logger.timeTracker.startWatch("Server Call");

                  },

                  success: function (data, status, jqXHR) {

                   timeStop = new Date();

                   console.log("timeStop: "+timeStop);

                   self.ajaxSuccess(data, status, jqXHR);//.apply(this, arguments);

                  },

                  complete: function () {

                   self.ajaxComplete.apply(this, arguments);

                  },

                  error: function (jqXHR, status, errorThrown) {

                   timeStop = new Date();

                   console.log("Proxy Error: HTTP" + jqXHR.status + " :: status = " + status + " :: error = " + errorThrown);

                   self.ajaxError.apply(this, arguments);

                  }

                 });

               

              2. Ruby code

               

              def proxy

                 url = @params['url']

                 data = @params['data']

                 headers = @params['headers']

                 clientCert = @params['clientCert']

                 clientPass = @params['clientPass']

                 serverCert = @params['serverCert']

                 method = @request['request-method']

                 headers['Origin'] = @request['headers']["Origin"]

               

                 Rho::RhoConfig.CAFile = "/mnt/sdcard/" + serverCert

               

                 #puts headers.inspect

                 elements = []

                 result = {}

               

                 if method == "GET"

                  data.each do |key, value|

                   elements << "#{key}=#{Rho::RhoSupport.url_encode(value)}"

                  end

               

                  url = url + "?#{elements.join('&')}"

                  result = Rho::AsyncHttp.get(

                   :url => url,

                   :headers => headers,

                   :clientSSLCertificate => clientCert,

                   :clientSSLCertificatePassword => clientPass,

                   :verifyPeerCertificate => true

                  )

                 else

                  result = Rho::AsyncHttp.post(

                   :url => url,

                   :body => data,

                   :headers => headers,

                   :clientSSLCertificate => clientCert,

                   :clientSSLCertificatePassword => clientPass,

                   :verifyPeerCertificate => true

                  )

                 end

               

                  puts "XXXXXX"

                  puts result.inspect

                  if result["status"] == "ok"

                    render :string => result["body"].to_json, :layout => false, :use_layout_on_ajax => true

                  else

                    @redirected = true

                    @response['status'] = result["http_error"].nil? ? 500 : result["http_error"]

                    @response['headers'] = result["headers"] if result["headers"]

                    #delete content-encoding because the controller always sends text.

                    @response['headers'].delete("content-encoding") if @response["headers"]

                    #for a 404 this would be something like "Not Found" This is not passed from the original call, so it needs to be put here

                    @response['message'] = 'Error message'

                  end

                 en

                • Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.
                  Kutir Mobility

                  In this case your ruby code is doing network operations (and apparently with SSL too) so it is likely that your bottleneck is not the javascript-ruby bridge. Why don't you add a few log statements recording the time at interesting points in your ruby code, like you have in javascript, and see what takes the most time to complete? I would add them

                   

                  • at the very beginning of the proxy method
                  • before calling get / post
                  • after calling get / post

                   

                  That will give you a better idea of how much time each operation takes. Then you can compare the time in beforeSend with the time at the beginning of the proxy method to measure how long it takes for the javascript request to reach ruby, and contrast that with the time spent in the network request, which is likely to be orders of magnitude larger.

                   

                  Javier

                  Kutir Mobility

                    • Re: Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.

                      Thanks Javier,

                       

                      We printed the logs on console. The deference between "before calling ruby method"(in javascript) and "at the very beginning of the proxy(Ruby) method" is 330ms. Please find the below console log. Can we reduce this time? Can you please suggest us. Thanks in advance.

                       

                      Console Log:

                       

                      I/APP     ( 4546): E 09/12/2013 06:39:36:097 000011c2 com.motorolasolutions.rhoelements.ElementsCore onConsole| JavaScript http://localhost:48497/public/MCF/ServerAccessManager.js, line 452: onConsole: Before Calling the Ruby method

                       

                       

                      D/ekioh   ( 4546): call void onLoadProgress

                       

                       

                      I/EkiohView( 4546): onLoadProgress 2061616/2061616

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:102 000011c2       RhoElementsExt| onNavigateProgress: url:

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:127 000011d0           HttpServer| Process URI: '/public/Images/splash.png'

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:131 000011d0           HttpServer| Process URI: '/public/Views/'

                       

                       

                      D/ekioh   ( 4546): call void onLoadProgress

                       

                       

                      I/EkiohView( 4546): onLoadProgress 2118539/2118539

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:133 000011c2       RhoElementsExt| onNavigateProgress: url:

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:153 000011d0           HttpServer| Process URI: '/app/Httpproxy/perfProxy'

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:154 000011d0                  APP| RHO serve: /app/Httpproxy/perfProxy

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:155 000011d0              RhoRuby| require_compiled: Httpproxy/httpproxy_controller

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:165 000011d0              RhoRuby| require_compiled: json

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:167 000011d0              RhoRuby| require_compiled: json/common

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:175 000011d0              RhoRuby| require_compiled: json/version

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:178 000011d0              RhoRuby| require_compiled: json/pure

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:183 000011d0              RhoRuby| require_compiled: json/pure/generator

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:199 000011d0              RhoRuby| require_compiled: net/http

                       

                       

                      D/szipinf ( 4546): Initializing inflate state

                       

                       

                      D/szipinf ( 4546): Initializing zlib to inflate

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:253 000011d0              RhoRuby| require_compiled: net/protocol

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:266 000011d0              RhoRuby| require_compiled: timeout

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:272 000011d0              RhoRuby| require_compiled: uri

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:274 000011d0              RhoRuby| require_compiled: uri/common

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:300 000011d0              RhoRuby| require_compiled: uri/generic

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:324 000011d0              RhoRuby| require_compiled: uri/ftp

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:330 000011d0              RhoRuby| require_compiled: uri/http

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:334 000011d0              RhoRuby| require_compiled: uri/https

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:336 000011d0              RhoRuby| require_compiled: uri/ldap

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:342 000011d0              RhoRuby| require_compiled: uri/ldaps

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:344 000011d0              RhoRuby| require_compiled: uri/mailto

                       

                       

                      I/APP     ( 4546): E 09/12/2013 06:39:36:355 000011d0              RhoRuby| require_compiled: error: can not find zlib

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:363 000011d0              RhoRuby| require_compiled: time

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:376 000011d0              RhoRuby| require_compiled: date/format

                       

                       

                      D/szipinf ( 4546): Initializing inflate state

                       

                       

                      D/szipinf ( 4546): Initializing zlib to inflate

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:426 000011d0                  APP| onConsole: Starting of ruby method

                       

                       

                      I/APP     ( 4546): I 09/12/2013 06:39:36:427 000011d0                  APP| onConsole: Request Received 2013-09-12 06:39:36

                        • Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.
                          Jon Tara

                          The deference between "before calling ruby method"(in javascript) and "at the very beginning of the proxy(Ruby) method" is 330ms. Please find the below console log. Can we reduce this time? Can you please suggest us.


                          Sure, there's a way to fix it. Tell the user to fly to whatever city the server is in. Preferably, then, you should ask the user to drive to the data-center location, and see if they have WiFi. The user should then connect to the data-center's WiFi, and I can guarantee that performance will be dramatically improved.


                          This may be a rather costly solution, however, as judging by the number above, it will almost certainly be an international flight. Make sure your user has his passport, immunizations, and any required visas.


                          Alternately, you might wish to hire a cable-laying ship, and lay a fibre-optic cable directly between the user's location and the data-center. You will need to install some equipment and, of course, a WiFi node. This is likely to improve the performance, but not as much as the first solution, and will be considerably more costly still.


                          Finally, you may just wish to move your server from where-ever it is now to the user's home/office/etc. This may require multiple servers. This should provide performance roughly equivalent to the first solution. However, performance will suffer if the user leaves the server location.


                          ----

                          Edit: I don't know what you measured, but it is irrelevant. I don't think you measured what Javier asked you to measure, but without seeing your source code, can't interpret your log. Do keep in mind that there can be some skew between Javascript and Rhodes logging. Unclear what you are showing in the log - it looks like application startup to me.


                          You may also be seeing some one-time startup latency - again - unclear what you are showing in the log above. But I see a bunch of Ruby modules being loaded. You wouldn't see this the second time you perform this operation, but if the additional latency the first time is a problem, you can solve it by requiring modules in your application.rb so that they all load at application startup.


                          There is going to be a significant latency accessing your server, and that is the real problem here. You are using AsyncHttp without a callback, which means you are using it synchronously. That means the entire app will wait for a reply from the server, and will be unresponsive during that time. You need to change your architecture and use an AsyncHttp callback and have the callback asynchronously update the page using either WebView.navigate or WebView.execute_js.


                          My experience is that latency between a Javascript request made to the Rhodes server is insignificant. But I don't use RhoElements.

                            • Re: Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.
                              Kutir Mobility

                              Hi there, Jon,

                               

                              I think Giri is using his ruby controller as a proxy to work around the same-origin limitation in javascript and the latency he is trying to measure is between Javascript and the ruby controller running on the mobile device.

                               

                              If his measurements are correct, he is seeing approximately 330 milliseconds. That seems too high and I think your experience confirms there is something we are not seeing that is affecting the results.

                               

                              Giri,

                              Let's see if there 's something we can do about it. First of all, I suggest we try to rule out as many factors as possible, so I would start from a brand new controller and view, (I called mine Perftest in the code below) and use these:

                               

                                def ruby_perftest
                                  start_time = Time.now.to_f
                                  render :string => {
                                    :start_time => start_time
                                  }.to_json, :layout=>false, :use_layout_on_ajax=>true
                                end
                              

                               

                               

                              function do_perf_test() {
                                var js_start_time = Date.now();
                                var ruby_start_time;
                                $.ajax({
                                dataType: "json",
                                url: "/app/Perftest/ruby_perftest",
                                success: function(data) {
                                ruby_start_time = data.start_time*1000;
                                console.log("ruby start time: "+ruby_start_time);
                                console.log("js start time  : "+js_start_time);
                                alert("Elapsed: "+(ruby_start_time - js_start_time)+" ms");
                                }
                                });
                              }
                              

                               

                              I believe that is as straightforward as it gets for what we're trying to do, and this should give us a measure of what is going on between Javascript and Ruby. Run the test a few times and post the values, let's see if what you get differs significantly between the first and subsequent runs. Then add the code to your existing Proxy controller and see if there is any difference in the elapsed test time.

                               

                              Javier

                              Kutir Mobility

                    • Re: Are there any techniques to removing latency between Ruby and Javascript service calls or improve performance.
                      Hector Meza

                      I wanted to close the loop on this - MSI support was able to dig deeper into this specific issue and has provided a option to address it.

                      Research:

                      After more investigation, this long delay only happens on the first load.

                          Here it shows that it had 351ms of overhead: 

                                I/APP     ( 3222): I 02/11/2011 12:37:07:892 00000ca7   

                               APP| POSConsole: ruby round trip duration @ 3096.588135 ms

                                I/APP     ( 3222): I 02/11/2011 12:37:07:923 00000c96 Low http://localhost:55240/public/App/index.html|
                      MCF:Process Log:--> POSConsole :Request round trip duration @ 3447 ms

                       

                          The next requests were much faster, taking only 25ms:

                               I/APP     ( 3222): I 02/11/2011 12:37:12:605 00000ca7      

                              APP| POSConsole: ruby round trip duration @ 982.8186039999999 ms

                              I/APP     ( 3222): I 02/11/2011 12:37:12:619 00000c96 Low http://localhost:55240/public/App/index.html|
                      MCF:Process Log:--> POSConsole :Request round trip duration @ 1007 ms

                           And the following taking  26ms

                       

                        

                      This has to do with the loading of ruby resources on the first load. I will be posting a way to load these files ahead of time, so no delay is encountered on the first load.

                       

                      Suggested Resolution:

                        To load the httpproxy_controller files at startup, after the first require statement in the application.rb, add the following:

                          

                      require 'Httpproxy/httpproxy_controller'

                          

                      After doing so, the first request now returns much quicker at 57ms for the first one:

                       

                          I/APP     ( 3481): I 02/11/2011 13:08:40:893 00000daa                

                          APP| POSConsole: ruby round trip duration @ 3178.710937 ms

                          I/APP     ( 3481): I 02/11/2011 13:08:40:917 00000d99 Low http://localhost:36899/public/App/index.html|
                      MCF:Process Log:--> POSConsole :Request round trip duration @ 3235 ms

                       

                      And 22ms for the next:

                           I/APP     ( 3481): I 02/11/2011 13:08:46:931 00000daa                

                          APP| POSConsole: ruby round trip duration @ 997.61963 ms

                          I/APP     ( 3481): I 02/11/2011 13:08:46:949 00000d99 Low http://localhost:36899/public/App/index.html|
                      MCF:Process Log:--> POSConsole :Request round trip duration @ 1019 ms

                       

                       

                      As you can see, the large delay of 300ms has been reduced to 57 ms for the first, and 23ms for subsequent calls. The first call appears to be delayed by initialization of classes, however it only adds 24 ms in doing so.