Thursday, July 17, 2008

Finetune ColdFusion Server Performance

Let me just put across some terminologies before I present my thoughts on improving/fine tuning the ColdFusion Server performance.

Request Wait Time
The number of milliseconds that a request was waiting in the queue before starting to execute.

Requests Running
The number of request currently under execution by server.

Request Execution Time
The number of milliseconds that a request took to execute on server.

Requests Queued
The number of queued requests that are waiting to be processed.

Keeping all the above terms in consideration the Response time could roughly be calculated as below...

HTTP Response time / PageLoad Time = "Webserver trip time for Browser and Application Server" + "Request Wait Time" + "HTTP Request Execution Time on Application Server"

Now, Before we move on let us know what different kind of requests ColdFusion server can handle.

What Kind of Requests can ColdFusion Server accept via HTTP ?

Currently with ColdFusion8, it accepts 4 kinds of requests via HTTP
1. CFML Template requests
2. Flash Remoting requests
3. WebService requests
4. CFC function requests

Each of the above 4 type of HTTP requests can be moderated for simultaneous request execution from "CFAdmin->ServerSettings->Request Tuning". So Next question here could be asked is, What should be the limit for each one of the above 4 ?

It depends, what kind of Applications are deployed on the ColdFusion server. One need to find out, which of the above 4 techniques are hugely used in the deployed Applications.

--> Traditionally ColdFusion Application generally uses CFML template Requests, so in this case increase the CFML template request accordingly.

--> With Flex/AIR technologies gaining momentum, a lot many Flash Remoting Calls could be coming into the server, so in this case it would make sense to increase the Flash Remoting Request Limit.

--> Likewise, if your application is hugely using CF WebService / CFC function requests then it would make sense to increase "webservice" and "CFC" request limits respectively.

ColdFusion uses JRun as underlying J2EE application server to run on. Here JRun is the master server which can control the simultaneous request execution limit. So Coldfusion has to respect this limit in order to moderate the simultaneous running request for the above 4 types of HTTP request, Meaning....... "Maximum number of running JRun threads Limit must be, greater than Simultaneous ( CFML Template + Flash Remoting + WebService + CFC ) Limits"
For example say,

CFML Template requests --> 20
Flash Remoting requests --> 20
WebService requests --> 10
CFC function requests --> 20
-----------------------------------------
Total --> 70

so, "Maximum number of running JRUN threads" must be greater than 70. If the value "Maximum Run Threads" is changed, then ColdFusion server needs to be restarted for the change to take effect

By how much we should/can increase the Request limits or What should be the threshold for Request Limits ? OR How to do the performance fine tuning for ColdFusion server ?

There is no standard formula to determine the thresholds. It depends on the machine/hardware capabilities on which the ColdFusion is deployed. Powerful the hardware(processor and memory), higher could be the threshold for each of those request limits. So how do you determine it?....It could be done by a trial and error method as mentioned below.

--> If the "Sum of (CFML+Flash+webService+CFC) Requests Running" value nearly matches the value of the "Maximum number of running JRUN threads" property, and also if the Requests Queued is large, and IF CPU USAGE IS LOW, you can increase the threshold for "CFML,Flash,webservice,CFC" and accordingly for "Maximum number of running JRUN threads".

Try this method starting with lower threshold values and keep increasing them until CPU usage is not underutilized. you would be able to determine the ideal load handling capabilities of your hardware by trying this method.

Note: The value of the "Maximum Running Run Threads" can significantly influence the scalability of your Web applications and the performance of your server.

So this trial and error approach to determine the threshold should be first tried on a similar configuration machine in development environment and then once you get your ideal threshold, same can be applied to ColdFusion server in production.

Ideally, the "Requests Queued" should remain close to zero; however, they can vary under varying loads (depending on the application) while the server still provides good performance.

If these numbers vary too much from their expected range, you might want to take Server Monitoring help to find out which portion of your code is taking too much time and accordingly might want to rewrite that portion of code to make it efficient.

If the queue size and wait time increases, or if the queue limit is reached, browser displays the HTTP error message "500/Server Too Busy".

Wednesday, July 16, 2008

Sample Flex File Upload Application

Recently I came across a thing where in I had to write a flex application which needs to upload file from the Client machine to Remote Application server, So I did some googling and came up with this simple demo application which explains most aspects of File upload functionality in Flex. I have tried to provide the inline comments in the below code to explain it. Refer http://livedocs.adobe.com/flex/2/langref/flash/net/FileReference.html for more information on Methods/events of FileReference package. Also, I found some cool multifile upload custom components but those were too complex for my need.

MXML/AS code of FileUpload:



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;

// This is the main library package which provided APIs/Events for FileUpload

import flash.net.FileReference;

private var fileRef:FileReference = new FileReference();
private var fileTypes:Array = new Array();

//setup the filters (types of files to be browsed)

private var imageTypes:FileFilter = new FileFilter("Images (*.jpg; *.jpeg; *.gif; *.png)" ,"*.jpg; *.jpeg; *.gif; *.png");
private var documentTypes:FileFilter = new FileFilter("Documents (*.pdf), (*.doc), (*.rtf), (*.txt)",("*.pdf; *.doc; *.rtf, *.txt"));

// Set Up URLRequest

public var uploadURL:URLRequest = new URLRequest();

public function init():void
{
// This URL should be replaced with your server side URL

uploadURL.url = "http://localhost/CF/upload/upload.cfm";
uploadURL.method = "GET"; // OR "POST" as you need it
uploadURL.contentType = "multipart/form-data";

// Event Listeners for UI Buttons (Upload/Browse)

browsebutton.addEventListener(MouseEvent.CLICK, browseFiles);
uploadbutton.addEventListener(MouseEvent.CLICK,uploadFiles);
fileRef.addEventListener(Event.SELECT, selectHandler);


}

//Browse for files

private function browseFiles(event:Event):void
{
fileTypes.push(imageTypes);
fileTypes.push(documentTypes);
fileRef.browse(fileTypes);

}

// called after user selects a file form the browse window.

private function selectHandler(event:Event):void
{
FilePath.text = event.currentTarget.name.toString();
}

// called when user clicks on the Upload button to upload the file

private function uploadFiles(event:Event):void
{
fileRef.addEventListener(Event.COMPLETE, completeHandler);
fileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,dataHandler);
fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS,httpStatusHandler);
fileRef.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
fileRef.upload(uploadURL);
}

// called after a file is uploaded

private function completeHandler(event:Event):void
{
Alert.show("File Uploaded successfully");
}

//called after file upload is done and Data has been returned from Server

private function dataHandler(event:DataEvent):void
{
resultsTxtField.text = event.data.toString();
}

// called if there is an error detected by flash player browsing or uploading a file

private function ioErrorHandler(event:IOErrorEvent):void
{
mx.controls.Alert.show(String(event),"ioError",0);
}
// called if a security error

private function securityErrorHandler(event:SecurityErrorEvent):void
{
mx.controls.Alert.show(String(event),"Security Error",0);
}
// server will return an http status code, code 200 means all is good

private function httpStatusHandler(event:HTTPStatusEvent):void
{
if (event.status != 200)
{
mx.controls.Alert.show(String(event),"Error",0);
}
}
]]>
</mx:Script>

<mx:Panel title="File Uploader">
<mx:ControlBar>
<mx:Spacer width="100%"/>
<mx:HBox>
<mx:TextInput id="FilePath" width="50"/>
<mx:Button id="browsebutton" label="Browse File" />
<mx:Button label="UpLoad File" name="uploadbutton" id="uploadbutton" />
</mx:HBox>
<mx:TextArea id="resultsTxtField"/>
</mx:ControlBar>
</mx:Panel>

</mx:Application>


Code for [http://localhost/CF/upload/upload.cfm] would be something as below in case of ColdFusion



<cffile action="upload" destination="C:\Inetpub\wwwroot\uploadClientfilesHere\" accept="application/octet-stream" FILEFIELD="filedata" nameconflict="overwrite" >