Tips, tricks and techniques to make your native RhoElements Apps faster, more responsive and more efficient.


From our last two developer forums in Bangkok and Birmingham our engineers have delivered an informative presentation on improving your native application performance, concentrating on both code optimization and database access.  Whilst the slides from this presentation are available (  I wanted to walk through some of the tips covered for those unable to attend the forums.





Here is a block diagram of a typical native RhoElements application.  A native application is such that it follows the MVC pattern of development, with your business logic stored as models on the device accessing data resident either on or off the device.  This blog will concentrate on those parts of the diagram coloured red and will assume your business logic is coded in Ruby.


Code Optimization


Any application developed for mobile devices must take the hardware constraints into account, this is true of any development framework and every mobile device.  Some of the key constraints are:

  • Device battery life
  • Available Memory

Power Consumption


The power consumption of your application will be affected by a number of factors but one of the most easily avoidable drains is polling. When writing your application you avoid polling for values from hardware where possible, instead you should register for callbacks to be notified when values change.  The RhoElements API is written almost exclusively to not require polling.


We can take callbacks a step further when we require the status of a server.  Polling a server to determine if our local copy of the database is up to date can be a very expensive, in terms of both Network load and battery life.  Network push notifications are an ideal work around to server polling and there are lots of platform specific push systems out there like iOS push or Google cloud messaging.  From RhoElements 2.2 onwards we ship with RhoConnect push, a new cross platform technology allowing you to do push without the need for a complex, managed solution involving Google or Apple.  You can check out the Webinar on the new RhoConnect push technology at


To further reduce your application's power consumption it can de-register callbacks and stop any other processing when it is sent into the background, this is acheived through the on_active_app and on_deactiveate_app overrides:


class AppApplication < Rho::RhoApplication
  def on_activate_app
    # restore all callbacks and js timers
  def on_deactivate_app
    # remove all unnecessary callbacks and js timers


For more information on the activate and deactivate callbacks see the documentation at




The following tips will ensure your application doesn't use excessive memory unnecessarily:


  • Don't use big global or class variables, all global and class variables will remain in memory until you nil them.  If you wish to maintain large persistent objects then they should be kept in a database and accessed through the database API,


  • Only load Ruby classes on demand as once loaded they remain in memory forever.  This will also decrease your application startup time.
def controller_action
require 'some_library'
#business logic


  • To improve application performance and stability the Ruby Garbage collector is disabled before each controller action and re-enabled after the controller action exits.  If you allocate / deallocate a lot of ruby objects in your controller action you should call it as follows:
def my_objects_generatorGC.enable
#Do some heavy operations



Performance Metrics


In order to analyse your application performance RhoElements offers metrics to detect inefficiencies and identify where you could speed up your code.




When written to the log file, logs will contain time information.  Using this time information you can get a quick and dirty idea of where your application performance is slow.


You can enable logging in your configuration file as follows:

MinSeverity = 1 #0 – trace, 1 – info, 3 - errors only
LogCategories = * # category1, category2
MaxLogFileSize=50000 # in kilobytes
LogMemPeriod=5000 #milliseconds


And in your application you can log with the following calls:

puts “Hello!” # will log with APP category
RhoLog.error("Some Category", "Some error message")"Some Category", "Some info message")




To better control and quantify your application's performance it is recommended to use the RhoProfiler,


Say you had two functions whose performance you wanted to measure, you would use the RhoProfiler as follows:

RhoProfiler.create_counter('Counter1') RhoProfiler.start_counter('Counter1') 
#do something 
RhoProfiler.stop_counter('Counter1') RhoProfiler.destroy_counter('Counter1')
# destroy_counter will log summary of function1 and function2 execution time


And that will write the resulting log as follows:

I 09/18/2012 23:27:20:311 00002ffc PROFILER| Counter1 (0:03:104) : STOP




Data Optimization


There are multiple ways of storing and manipulating data with RhoElements

  • PropertyBag (generated by default)
  • Data Schema
  • RhoConnect (to connect with data at the back end)


Data storage techniques are discussed in more detail at the documentation page for rhom,  Rhom is a mini database object mapper for RhoElements, providing high level interfaces to use a local database.


You may choose to use a PropertyBag or Fixed Schema for data storage


Property Bag


Simple to use, it doesn't require specifying attributes in the model definition file.

Data migrations are not necessary

Attributes can be added ore removed without modifying the database schema

For some applications, the database size may be significantly larger than for fixed schema.  This is because each attribute is indexed for fast lookup.


Fixed Schema


Smaller database size, indexes can be specified only on specific attributes.

You may use direct SQL queries if and when required.

Schema changes must be handled with data migrations

Database performance may be slower unless you specify proper indices




Pre-populating the database


If your application requires seeding of initial data then you can use RhoUtils.load_offline_data.

For example, in the rhodes/spec/framework_spec, we use load_offline_data to seed the device database for each test: 

  ['client_info','object_values'], 'spec'


In this example, there is a ‘spec/fixtures’ directory which contains a client_info.txt and object_values.txt pipe-delimited files. For more information on this please see the online documentation at


You might also consider creating the local database file beforehand, then including the .db file in your application at deployment.  You can use the emulator to achieve this and there is documentation online at




Often you'll be dealing with long lists of data that the user has to scroll through.  It is very inefficient (and slow) to try and load this entire list all at once, the recommended solution is to use pagination to display say 20 records at a time.  The rhom API offers a syntax identical to rails' syntax and is documented at

Account.paginate(:page => 0) 
  #=> returns first 10 records
Account.paginate(:page => 1, :per_page => 20) 
  #=> returns records 21-40
  :page => 5, 
  :conditions => {'industry' => 'Technology'}, 
  :order => 'name'
) #=> you can have :conditions and :order as well



Tips for using the Property Bag model


Do not use SQL conditions in Model.find, use Advanced queries instead (


#Let’s say we have the following SQL fragment condition:
Product.find( :all, :conditions => [ "LOWER(description) like ? or LOWER(title) like ?", query, query ], 
:select => ['title','description'] ) 

#Using advanced :conditions, this becomes:
Product.find( :all, :conditions => { 
  { :func => 'LOWER', :name => 'description', :op => 'LIKE' } => query, 
  { :func => 'LOWER', :name => 'title', :op => 'LIKE' } => query }, 
  :op => 'OR', 
  :select => ['title','description'] ) 


To modify an object in the database, prepare the data first and call update_attributes once.  Do not use save

props = {"name" => "ABC Inc.", “brand" => “Comp2"}
@product.update_attributes( props )


To insert or update multiple objects or models use a database transaction


db = ::Rho::RHO.get_src_db('Model') 
  items.each do |item| 
    # create hash of attribute/value pairs 
    data = { :field1  => item['value1'], :field2 => item['value2'] } 
    # Creates a new Model object and saves it    
    new_item = Model.create(data) 




For more information on RhoConnect then please see the user documentation at, it's a large topic which I would not be able to adequately cover in this blog.


If your application solution uses RhoConnect to sync its data with the backend database you might consider using bulk sync,


Enabling bulk sync either in your configuration file or at runtime will cause the next synchronization with the back end to first be zipped up before being sent to the device. 


To enable bulk sync in your configuration add:

bulksync_state = 0


To enable bulk sync at runtime call:

Rho::RhoConfig.bulksync_state = '0‘


The following actions are performed for a bulk sync:

  • The RhoConnect server prepares the sqlite database, zipps it and sends it to the client, running on your mobile device.
  • The RhoConnect client receives the database, unzips it and replaces the database on the device, without the overhead of SQL inserts.