The performance of Ruby on Rails

Rails Articles No Comments »

The performance of Ruby on Rails is influenced by many factors, particularly the configuration of your deployment server(s). However the application code can make a big difference and determine whether your site is slow or highly responsive. This short article is about some of the tips and best coding practices to improve performances in Rails only, and won’t attempt to cover the server configuration improvements for the various deployments options. 

  1. Optimize your Ruby code: this may seem obvious, but a Rails application is essentially ruby code that will have to be run. Make sure your code is efficient from a Ruby standpoint. Take a look at your code and ask yourself if some refactoring is in order, keeping in mind performance considerations and algorithmic efficiency. Profiling tools are, of course, very helpful in identifying slow code, but the following are some general considerations (some of them may appear admittedly obvious to you):
    • When available use the built-in classes and methods, rather than rolling your own;
    • Use Regular Expressions rather than costly loops, when you need to parse and process all but the smallest text;
    • Use Libxml rather than the slower REXML if you are processing XML documents;
    • Sometimes you may want to trade off just a bit of elegance and abstraction for speed (e.g. define_method and yield can be costly);
    • The best way to resolve slow loops, is to remove them if possible. Not always, but in a few cases you can avoid loops by restructuring your code;
    • Simplify and reduce nested if/unless as much as you can and remember that the operator ||= is your friend;
    • Hashes are expensive data structures. Consider storing the value for a given key in a local variable if you need to recall the value a few times. More in general, it’s a good idea to store in a variable (local, instance or class variable) any frequently accessed data structure.
  2. Caching is good: caching can significantly speed up your application. In particular:
  3. Use your database to the full extent of the law ): don’t be afraid of using the cool features provided by your database, even if they are not directly supported by Rails and doing so means bypassing ActiveRecord. For example define stored procedures and functions, knowing that you can use them by communicating directly with the database through driver calls, rather than ActiveRecord high level methods. This can hugely improve the performance of a data bound Rails application.
  4. Finders are great but be careful: finders are very pleasant to use, enable you to write readable code and they don’t require in-depth SQL knowledge. But the nice high level abstraction come with a computational cost. Follow these rules of thumb:
    • Retrieve only the information that you need. A lot of execution time can be wasted by running selects for data that is not really needed. When using the various finders make sure to provide the right options to select only the fields required (:select), and if you only need a numbered subset of records from the resultset, opportunely specify a limit (with the :limit and :offset options).
    • Don’t kill your database with too many queries, use eager loading of associations through the include option:
o                     # This will generates only one query,
o                     # rather than Post.count + 1 queries
o                     for post in Post.find(:all,
o                                           :include => [ :author, :comments ])
o                       # Do something with post
end
  1.  
    • Avoid dynamic finders like MyModel.find_by_*. While using something like User.find_by_username is very readable and easy, it also can cost you a lot. In fact, ActiveRecord dynamically generates these methods within method_missing and this can be quite slow. In fact, once the method is defined and invoked, the mapping with the model attribute (username in our example) is ultimately achieved through a select query which is built before being sent to the database. Using MyModel.find_by_sql directly, or even MyModel.find, is much more efficient;
    • Be sure to use MyModel.find_by_sql whenever you need to run an optimized SQL query. Needless to say, even if the final SQL statement ends up being the same, find_by_sql is more efficient than the equivalent find (no need to build the actual SQL string from the various option passed to the method). If you are building a plugin that needs to be cross-platform though, verify that the SQL queries will run on all Rails supported databases, or just use find instead. In general, using find is more readable and leads to better maintainable code, so before starting to fill your application with find_by_sql, do some profiling and individuate slow queries which may need to be customized and optimized manually.
  2. Group operations in a transaction: ActiveRecord wraps the creation or update of a record in a single transaction. Multiple inserts will then generate many transactions (one for each insert). Grouping multiple inserts in one single transaction will speed things up.

Insead of:

 my_collection.each do |q|
   Quote.create({:phrase => q})
 end

Use:

Quote.transaction do
 my_collection.each do |q|
   Quote.create({:phrase => q})
 end
end

or for rolling back the whole transaction if any insert fails, use:

Quote.transaction do
 my_collection.each do |q|
   quote = Quote.new({:phrase => q})
   quote.save!
 end
end
  1. Control your controllers: filters are expensive, don’t abuse them. Also, don’t overuse too many instance variables that are not actually required by your views (they are not light).
  2. Use HTML for your views: in your view templates don’t overuse helpers. Every time you use form helpers you are introducing an extra step. Do you really need a helper to write the HTML for a link, a textbox or a form for you? (You may even make your designer, who doesn’t know Ruby, happy!)
  3. Logging: configure your applications so that they log only the information that is absolutely vital to you. Logging is an expensive operation and an inappropriate level (e.g. Logger::DEBUG) can cripple your production application.
  4. Patch the GC: OK, not really a coding issue, but patching Ruby’s Garbage Collection is strongly advised and will improve the speed of your Ruby and Rails applications significantly.
  5. A final note:I don’t advocate premature optimization, but if you can, work on your code with these principles in mind (but don’t overdo it either). Last minute changes and tweaks are possible but less desirable than a “performance aware” style of coding. Profile your applications, benchmark them
    and have fun experimenting.

 

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • blogmarks
  • Book.mark.hu
  • co.mments
  • Technorati
  • YahooMyWeb
  • IndianPad
  • DZone

Playing Flv Files in Ruby On Rails (Part 3)

Ruby On Rails No Comments »

Taking screenshots of the uploaded video using the FFMPEG Plugin 

Hey, now its time to take photos from your uploaded videos…I hope that sounds good

 

Anyways,It will be a simple job if you have achieved success in integrating the mencoder into the app.

 

So,lets start talking about the FFMPEG encoder.The FFMPEG encoder works similar to the Mencoder utility.But,the only difference is that it provides more control over the video.It provides the image capturing facilty which techies generally call screenshots.

Using the FFMPEG utility we can generate screenshots of various sizes and also develop thumbnails for our rails app.

 

In order to download the FFMPEG utilty,check the following link

 

http://www.free-codecs.com/ffmpegGUI_download.htm

or

http://www.videohelp.com/tools/ffmpeg

 

Then u just have to copy the files from the unzipped folder into the mplayer folder in the public directory of our application.

 

For the documentation with respect to the usage of the ffmpeg codec please visit the following site:

 

http://ffmpeg.mplayerhq.hu/documentation.html

The following function takes the responsibility of generating the screenshots of the uploaded video

def self.grab_screenshot_from_video(path,name,video_id)

      memdir = RAILS_ROOT+’/public/mplayer/’

      opdir = RAILS_ROOT + “/#{video_id}/”+name

      jpgdir =RAILS_ROOT + “/#{video_id}/”+name

      #conversion to mencoder format

      system “#{memdir}ffmpeg -i #{opdir}.flv -s 320×240 -vframes 1 -f image2 -an #{jpgdir}.jpg”

   end

 

The grab_screenshot_from_video takes the path of the generated video as the input and passes the video to the FFMPEG commandline utility to generate an image of size 320×240 and then saves the image in the jppdir.

 

NOTE:

 Here I have placed the FFMPEG utilty in the mplayer directory in thr public folder of our app.

Please do read at the following section reagarding the compatibility and testing of the FFMPEG encoderhttp://ffmpeg.mplayerhq.hu/compat.html

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • blogmarks
  • Book.mark.hu
  • co.mments
  • Technorati
  • YahooMyWeb
  • IndianPad
  • DZone

Playing Flv Files in Ruby On Rails (Part 2)

Ruby On Rails No Comments »

Assuming the basic stuff in our hands, we can  now move on to the development of the flash video playback

 

The basic functionality of the  video app has been defined with the following inputs and outputs:

The user uploads the video using the user interface

The video is then converted into the flv format using the mencoder command line converter

The converted video is then played in the flv player in the browser output.

 

So, lets start off with the database stuff,the following is the basic structure of the database which I have been using for the demo

Just Posting the migration file.

 

class CreateVideos < ActiveRecord::Migration

  def self.up

    create_table :videos do |t|

      t.column :video_data, :string

    end

  end

 

  def self.down

    drop_table :videos

  end

 

end

This is  just a basic database which saves the video_name and the id of the video.You can customize this file to save more info related to the video.

 

 

Now,First of all, I generate a controller named Upload Controller which handles the basic actions for video conversion

 

FileName:upload_controller.rb

 

class UploadController < ApplicationController

 

 

  def convert

    render :file => ‘app/views/upload/convert.rhtml’

  end

 

The convert action render the input file for the video i.e  the webpage from the video is supposed to be uploaded.

 

 

 

  def show_video

  if request.get?

      @video = Video.new

    else

      @video = Video.new(params[:video])

      if @video.save

      upload = Video.convert_to_flv(@video)

      @file_data = Video.find(:first, :select=>’DISTINCT id,video_data’,:conditions =>[’video_data=?’,@video[”video_data”]],:order => “id DESC”)

      @video_data= “/video/video_data/”+ “#{@file_data[”id”].to_s }/”+ “#{@file_data[”video_data”]}.flv”      

flash[:notice]=”Hey,Your video has been uploaded successfully”

       render :file => ‘app/views/upload/show_video.rhtml’

    else

      flash[:notice]=”Hey,There was an error processing your video”

  end

  end

end

end

 

The show video is the action which handles the conversion of the input video and also the display of the video to the output page.

The action receives the parameters named video from the input page and before saving the video converts the video to the flv format

The convert_to_flv takes the @video as the parameter and converts it into the flv format which we will see later.

The @file data is nothing but a result set which holds the data of the query which gets the information related to the latest uploaded video by the user.

The @video_data passes the path to the video  to the output flv player

 

FileName: convert.rb

 

<%= form_tag({:action=>’show_video’},{:multipart=>true}) %>

    <%=file_column_field(”video”,”video_data”,:size=>”15″)%>

</p>

    <p>

      <input name=”convert_submit” type=”submit” value=”Convert_submit” id=”convert”>

    </p>

<%=end_form_tag%>

 

 

Here I am using the file column plugin to upload the video and the form action pointing to the action show_video

 

FileName: show_video.rb

 

<%= javascript_include_tag ‘ufo’ %>

<h> Show Video </h></br>

<%=flash[:notice]%>

<% p “video data from the view”%>

<% p @video_data%>

<%=flv_player :file =>@video_data %>

 

 

The show video represents the output file of the flv player.The Javascript include tag includes the ufo.js which comes bundled with the flash player helper plugin and  needs to be explicitly included in your application.

NOTE: The ufo.js can be included to application.rb when it comes to a development of the big app.

The flv_player tag adds an flv player to the page with the input.For more customization with respect to the player You can visit the farooq ali’s blog  which I have mentioned in my previous post.

 

Now the last and the most important, The model file

 

FileName:Video.rb

 

class Video < ActiveRecord::Base

  file_column :video_data

 

  def self.convert_to_flv(upload)

      full_name =  upload.video_data

      name_array = full_name.split(”/”)

       name = name_array[name_array.length-1]

      directory = “public/video/video_data/#{upload.id}”

    # create the file path

        path = File.join(directory, name)

      if !name.nil?

        convert_video_to_flv(path,name, directory)

      end

    end

 

The convert_to_flv takes the input video and strips out the filename from the parameter and creates a directory under the directory path given above with the id  and saves the uploaded file there.

The uploaded file is then passed to the convert_video_yo_flv method which we will see below.

 

 

 

  def self.convert_video_to_flv(path,name,video_id)

      memdir =RAILS_ROOT + ‘/public/mplayer/’

      opdir = RAILS_ROOT + “/#{video_id}/”+name+”.flv”

      filepath = RAILS_ROOT + “/#{video_id}/”+name

      system “#{memdir}mencoder #{filepath} -o #{opdir} -of lavf -oac mp3lame -lameopts abr:br=56 -srate 22050 -ovc lavc -lavcopts vcodec=flv:vbitrate=500:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames”

      File.delete(”#{filepath}”)

    end

end

 

The convert_video_to_flv  takes the path, name and the video_id as the parameter and then uses the  mencoder command line utility to convert the video to flv format.

And then deletes the original file after conversion ,which the user has uploaded ,mainly to save the server space.

 

I am also posting the following links with respect to the mencoder command which will help u take more control over the commanline

HOWTO Mencoder Introduction Guide

http://gentoo-wiki.com/HOWTO_Mencoder_Introduction_Guide

 

Basic usage of Mencoder

http://www.mplayerhq.hu/DOCS/HTML/en/mencoder.html

 

Encoding with the libavcodec codec family

http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-enc-libavcodec.html

 

Now,Before I hang up this post of mine, I would like mention a few checkpoints with respect to the conversion and  the code also.

 

  1. The code if mine can be still refactored by keeping the model loose and placing the methods from to the upload_helper in your app and then calling those method conveniently before save.
  2. During the conversion of 3gp file to flv format, it may  happen that the video may not play the sound.This is mainly because of the AMR sound codec,I have been working on this issue and will soon post the resolution as the AMR codec is been integrated with the mplayer.

 

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • blogmarks
  • Book.mark.hu
  • co.mments
  • Technorati
  • YahooMyWeb
  • IndianPad
  • DZone

Playing Flv Files in Ruby On Rails (Part 1)

Ruby On Rails No Comments »

Playing Flv Files in Ruby On Rails (Part 1) 

Rails has been a great and powerful framework for me since I have got in touch with. This time in order to test the power of Rails framework, I choose to play with the flash based video playback for web apps using the rails framework.

 

Before we actually get our hands dirty in writing the core programs of video playback, we first need to check out the requirement and the basic knowledge of the requirements that are actually required as a part of the development process.

 

The following listing provides the basic tools and equipments that should be in our hand before we start off with the development

 

1.Flash Player Helper Plugin:

This is the first most important tool which we require for playing the video file.

You can Install the plugin into your Rails App from the following site:

ruby script/plugin install svn://rubyforge.org/var/svn/flashplayrhelpr

 

For actually integrating the plugin into your application use the rake:

rake flash_player:install

That’s gonna install the falsh player into your application.

 For more information regarding the plugin please visit :

http://www.jroller.com/abstractScope/entry/flash_mp3_imageslideshow_media_player

And not forgetting a thanks to farooq ali for a great tutorial regarding the integration of the plugin into the rails app.

 

 

2 .File Column Plugin for File Upload:

 You can download and  install the file column plugin from the following location:

ruby script/plugin install http://opensvn.csie.org/rails_file_column/
   plugins/file_column/trunk

 

For more information of the plugin and its usage please visit:

http://www.kanthak.net/opensource/file_column/

 

3.Mplayer/Mencoder:

The basic task of a mencoder which comes bundled with the mplayer, is mainly used for the conversion of  the a movie file(basics format .WMV,.AVI …etc). into .FLV(Flash Video) format .

In order to download the mencoder(MPlayer 1.0rc1 Windows), please refer to the instruction on the following site

http://www.cscs.ch/~mvalle/mencoder/mencoder.html

 

We will discuss the integration of mencoder into our Rails app in the second part of this tutorial

 

 

 

4.Video Codecs:

These are the most important role playing stuff when it comes to video conversion from one format to the other.

You can download the latest version of the codecs(Windows x86 20071007) from the following location:

http://www4.mplayerhq.hu/homepage/design6/dload.html#binary_codecs

 

Configuration of codecs in Mplayer/Mencoder 

When you download the codec pack from the mplayer site .You will find that the codecs are mere dll files. So in order to use these codecs ,what we have to do is copy the all the dll files into the codecs folder in the mplayer directory

 

NOTE: Please create a codecs folder if not present and do not forget to read the readme in the mplayer source directory for more information

 

With these basic configuration in hand we can now move to develop a Rails app for flash Video playback in the upcoming part

 

           

 

 

 

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • blogmarks
  • Book.mark.hu
  • co.mments
  • Technorati
  • YahooMyWeb
  • IndianPad
  • DZone

Validating XSD against XML In Ruby On Rails.(Part 2)

Ruby On Rails 5 Comments »

 Before I actually run into the development of the xsd helper, I would like to express some few points regarding how this helper will actually work:

1.The input to the xsd helper will be an xml file and an xsd file against which the ml is supposed to be validated

2. the Output will be the a message indicating the validation status.

So, here goes the actual helper i.e Xsd_Helper.rb

module XsdHelper

I require the fileutils and tempfile libs for file object manipulation

  require ‘fileutils’

  require ‘tempfile’

I define the FILE_HOME  and the XML_STARTLET HOME.In the file home, I create 2 files finalxsd.xsd and finalxml.xml which we are going to see later.In the xmlstartlet home I keep the xmlstartlet library.Here I have kept the library in the public folder of our app.

    FILE_HOME = “#{RAILS_ROOT}/public/temp”

    XMLSTARTLET_HOME =”#{RAILS_ROOT}/public/xmlstartlet”

Now , we write the actual method which validates the xml against the xsd. We pass 2 parameters to the method i.e the xsdfile and the xmlfile

   def validate_xml_to_xsd(xsdfile,xmlfile)

@temp_xsd =validate(xsdfile)

            @temp_xml =validate(xmlfile)

We have to validate the xmlfiles and xsdfiles type in this case since in rails files below the size of 10kb are passed as a STRINGIO object and files above 10kb are passed as the TempFile Object . So, This validate method converts the STRINGIO object into the TEMPFILE object .

   

     finalxsd = File.new(FILE_HOME+”/finalxsd.xsd”,”w”)

     finalxml = File.new(FILE_HOME+”/finalxml.xml”,”w”)

Here,I create 2 new files in the FILE_HOME named finalxsd.xsd and finalxml.xsd.the purpose of these 2 files is, since, xmlstartlet library takes does not support the tempfile object

  FileUtils.copy(”#{@temp_xsd.path}”,”#{finalxsd.path}”)

  FileUtils.copy(”#{@temp_xml.path}”,”#{finalxml.path}”)

Here I copy the two file content from the temporary file to the respective xml and xsd file command_line=”#{XMLSTARTLET_HOME}/xml val -s “+ “#{finalxsd.path}” +’ ‘+”#{finalxml.path}”

  result_string = %x[#{command_line}] 

Then , I pass the two files to the xmlstratlet commandline utility for the actaual validation of the xml file

 assess_validation_result(result_string)

The access validation result takes the result string as the input and customizes the output which is returned to our rails controller as a Boolean output

   end

 

  private

 

  def assess_validation_result(result_string)

                        if (result_string=~/.+xml - invalid/).nil? then

                  true

                        else

                    raise result_string 

                        end

  end

       

def validate(file)

  @file = file

  # @file should contain file uploaded by HTTP

  # it is either StringIO object (if file was smaller than 10Kb)

  # or Tempfile (otherwise)

  if not (@file.kind_of? StringIO or @file.kind_of? Tempfile)

       return

  end

   if @file.kind_of? StringIO

    # Yes, if @file is StringIO, create new Tempfile and copy everything to it

     @real_file = Tempfile.new(”tempofile”)

    while not @file.eof?

      @real_file.write @file.read

    end

  else

   # Most uploads will be Tempfiles

    @real_file = @file

  end

   return @real_file

end

end

So,finally in the controller action, You can call the validate_xml_to_xsd(xsdfile,xmlfile) as ashoen below:

def input
    if request.post? && !params.nil?    
        @validate_output = validate_xml_to_xsd(params[’fileinfo’][’xsd_file’],params[’fileinfo’][’xml_file’])

if(@validate_output == true)

             flash[:notice] =”Your xml has been successfully validated”

end

render :action =>  ‘output’
      else
        render :action => ‘input’

       flash[:notice] = “Failed to validate the xml file”
          end
     end
end

 

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • blogmarks
  • Book.mark.hu
  • co.mments
  • Technorati
  • YahooMyWeb
  • IndianPad
  • DZone

WordPress Theme & Icons by N.Design Studio. Packaged by Edublogs - education blogs.
Entries RSS Comments RSS Login