But when you have a choice then you need to know what is the best communication method for your project. In this test I will measure the performance of the three methods. For this I made a simple Flex / Ruby project.
Here are the average results in ms (100 times executed) with the total records count in our test table.
records | 10 | 100 | 400 | 1000 |
amf | 159 | 213 | 380 | 731 |
json | 45 | 75 | 252 | 781 |
xml | 43 | 57 | 197 | 612 |
Conclusion
RubyAMF has a little overhead and is fast with a large recordset and you can use remoteobject in Flex. Xml is fast but the performance can vary. With 1000 records it can take 200ms but sometimes 2000ms. It looks like Ruby can cache xml and sometimes refresh the cache. Json is very stable and fast with small recordsets. If you just want to retrieve some data in Flex, I would use json but when you want to do more with this data in Flex then RubyAMF has many benefits, like association between objects, conversion to actionscript class and a lot more.
The Ruby Code
you can test the output by adding the format parameter to the url http://localhost:3000/departments/find_all?format=json or format=xml.
Here is the controller code I used
class DepartmentsController < ApplicationController
# return all Departments
def find_all
respond_to do |format|
format.amf { render :amf => Department.find(:all) }
format.json { render :text => Department.find(:all).to_json }
format.xml { render :xml => Department.find(:all) }
end
end
end
department table created in a mysql database
class CreateDepartments < ActiveRecord::Migration
def self.up
create_table :departments do |t|
t.string :name
t.string :location
t.timestamps
end
end
def self.down
drop_table :departments
end
end
RubyAMF configuration
require 'app/configuration'
module RubyAMF
module Configuration
ClassMappings.ignore_fields = ['created_at','updated_at']
ClassMappings.translate_case = true
ClassMappings.assume_types = false
ParameterMappings.scaffolding = false
ClassMappings.register(
:actionscript => 'Department',
:ruby => 'Department',
:type => 'active_record',
:attributes => ["id", "name", "location", "created_at", "updated_at"])
ClassMappings.force_active_record_ids = true
ClassMappings.use_ruby_date_time = false
ClassMappings.use_array_collection = true
ClassMappings.check_for_associations = true
ParameterMappings.always_add_to_params = true
end
end
The Flex code
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import vo.Timing;
private var idNum:int;
private var maxNum:int = 100;
[Bindable]
private var timing:ArrayCollection = new ArrayCollection();
private function startRubyAMF():void {
timing = new ArrayCollection();
idNum = 0;
loadAll();
}
private function startJSON():void {
timing = new ArrayCollection();
idNum = 0;
loadAllJson();
}
private function startXML():void {
timing = new ArrayCollection();
idNum = 0;
loadAllXML();
}
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable]
private var departments:ArrayCollection = new ArrayCollection();
private var rubyDateFrom:Date;
private function loadAll():void {
rubyDateFrom = new Date();
var token:AsyncToken = AsyncToken(departmentService.find_all());
token.kind = idNum.toString();
var time:Timing = new Timing();
time.id = idNum;
time.startDate = rubyDateFrom;
timing.addItem(time);
}
private function faultHandler(event:FaultEvent):void {
Alert.show(event.fault.faultString + " : " + event.fault.faultCode + " : " + event.fault.faultDetail , "Error in LoginCommand");
}
private function resultHandler(event:ResultEvent):void {
departments = event.result as ArrayCollection;
var rubyDateFinish:Number = new Date().valueOf() - rubyDateFrom.valueOf() ;
rubyLabel.text="RubyAMF departments "+rubyDateFinish.toString()+" ms";
var time:Timing = timing.getItemAt(event.token.kind) as Timing;
time.endDate = new Date();
time.rubyamf = rubyDateFinish;
idNum = idNum +1;
if (idNum < maxNum ) {
loadAll();
} else {
var average:Number = 0;
for ( var i:int = 0 ; i < timing.length ; i++ ) {
var time2:Timing = timing.getItemAt(i) as Timing;
average = average + time2.rubyamf;
}
average = average / timing.length;
rubyLabel.text="RubyAMF departments average "+average.toString()+" ms";
trace("end");
}
}
]]>
</mx:Script>
<mx:HBox>
<mx:Button label="refresh RubyAMF" click="startRubyAMF()"/>
<mx:Button label="refresh JSON" click="startJSON()"/>
<mx:Button label="refresh XML" click="startXML()"/>
</mx:HBox>
<mx:RemoteObject id="departmentService" destination="rubyamf"
endpoint="http://localhost:3000/rubyamf_gateway/"
source="DepartmentsController"
showBusyCursor="true"
result="resultHandler(event)"
fault="faultHandler(event)"
/>
<mx:Label id="rubyLabel" text="RubyAMF departments"/>
<mx:DataGrid id="dg" dataProvider="{departments}">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Key"/>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="location" headerText="Location"/>
</mx:columns>
</mx:DataGrid>
<mx:Script>
<![CDATA[
import com.adobe.serialization.json.JSON;
[Bindable]
private var dp:ArrayCollection = new ArrayCollection() ;
private var rubyJsonDateFrom:Date;
private function loadAllJson():void {
rubyJsonDateFrom = new Date();
var token:AsyncToken = AsyncToken(json.send());
token.kind = idNum.toString();
var time:Timing = new Timing();
time.id = idNum;
time.startDate = rubyJsonDateFrom;
timing.addItem(time);
}
private function resultHandlerJSON(event:ResultEvent):void
{
dp = new ArrayCollection();
var rawData:String = String(event.result);
var arr:Array = (JSON.decode(rawData) as Array);
for ( var i:int = 0 ; i < arr.length ; i++ ) {
dp.addItem(arr[i].department);
}
var rubyJsonDateFinish:Number = new Date().valueOf() - rubyJsonDateFrom.valueOf() ;
rubyJSONLabel.text="JSON departments "+rubyJsonDateFinish.toString()+" ms";
var time:Timing = timing.getItemAt(event.token.kind) as Timing;
time.endDate = new Date();
time.json = rubyJsonDateFinish;
idNum = idNum +1;
if (idNum < maxNum ) {
loadAllJson();
} else {
var average:Number = 0;
for ( var ii:int = 0 ; ii < timing.length ; ii++ ) {
var time2:Timing = timing.getItemAt(ii) as Timing;
average = average + time2.json;
}
average = average / timing.length;
rubyJSONLabel.text="JSON departments average "+average.toString()+" ms";
trace("end");
}
}
]]>
</mx:Script>
<mx:HTTPService id="json"
url="http://localhost:3000/departments/find_all?format=json"
result="resultHandlerJSON(event)" useProxy="false" />
<mx:Label id="rubyJSONLabel" text="JSON departments"/>
<mx:DataGrid id="dg4" dataProvider="{dp}">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Key"/>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="location" headerText="Location"/>
</mx:columns>
</mx:DataGrid>
<mx:Script>
<![CDATA[
import com.adobe.serialization.json.JSON;
[Bindable]
private var dp2:ArrayCollection = new ArrayCollection() ;
private var rubyXmlDateFrom:Date;
private function loadAllXML():void {
rubyXmlDateFrom = new Date();
var token:AsyncToken = AsyncToken(xml.send());
token.kind = idNum.toString();
var time:Timing = new Timing();
time.id = idNum;
time.startDate = rubyJsonDateFrom;
timing.addItem(time);
}
private function resultHandlerXML(event:ResultEvent):void
{
if ( event.result != null ) {
dp2 = event.result.departments.department;
}
var rubyXmlDateFinish:Number = new Date().valueOf() - rubyXmlDateFrom.valueOf() ;
rubyXmlLabel.text="XML departments "+rubyXmlDateFinish.toString()+" ms";
var time:Timing = timing.getItemAt(event.token.kind) as Timing;
time.endDate = new Date();
time.xml = rubyXmlDateFinish;
idNum = idNum +1;
if (idNum < maxNum ) {
loadAllXML();
} else {
var average:Number = 0;
for ( var ii:int = 0 ; ii < timing.length ; ii++ ) {
var time2:Timing = timing.getItemAt(ii) as Timing;
average = average + time2.xml;
}
average = average / timing.length;
rubyXmlLabel.text="XML departments average "+average.toString()+" ms";
trace("end");
}
}
]]>
</mx:Script>
<mx:HTTPService id="xml" url="http://localhost:3000/departments/find_all?format=xml"
result="resultHandlerXML(event)" useProxy="false" />
<mx:Label id="rubyXmlLabel" text="XML departments"/>
<mx:DataGrid id="dg5" dataProvider="{dp2}">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Key"/>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="location" headerText="Location"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
No comments:
Post a Comment