Archive for May, 2010

CFBuilder tip : TailView can kill server performance

If you use ColdFusion Builder and if you use tailview, this post is for you! Tail View is a great functionality in ColdFusion builder that allows you to tail the contents of any log file in real time. It is a great productivity feature that saves you from opening the log file and continuously reloading it.

TailView in ColdFusion Builder keeps watching the file for any modification and if there is any, it updates the view with the latest content. That causes a race condition between the tail view process which is trying to read the file and the server process that is writing to the same file. Generally, in such race conditions, the preference is almost always given to the reader. If there is any read operation (and there can be multiple simultaneous reads) in progress, write operation waits.

Somehow this race condition is not very much visible when the server is running from console. However, when the server is running as a service, this race condition becomes so severe that the server becomes almost unresponsive. The jrunsvc.exe process just hogs up all the CPU cycles and the server becomes nearly dead.

A simple way to fix this is to increase the period at which the tail view checks for a change in the file content. Thankfully ColdFusionBuilder provides a preference to do that.
Go to Windows > Preference > HTML >TailView and change the value of “Read Timeout” from 100 to 1000 or any other suitable higher value. This will give enough time to server threads to write contents to the log file.

Tags: , , ,

EntityReload and performance

I received a small test application today for a bug, that said that the EntityReload performance was really bad. My first reaction was – there is nothing much we can do – thats all Hibernate code there. On a second thought, I decided to have a look at the application. The application had an object where one of the field’s value was generated by DB. Since the application never sets the value for this property while insertion, it had defined the property with attribute “insert” set to false. When the object is saved, the sql does not include this property and hence its value is generated by the database. So far so good. However the application needs to get the value that is generated by the database immediately after the object is saved. In order to do that, the application calls EntityReload() on the object and the generated value for the property gets loaded. Perfect? Not at all.

Here is the simplified component definition

/**
* @persistent
*/
Component Group
{
/**
* @fieldtype Id
* @generator native
*/
property id;
 
property name;
 
/**
* @dbdefault "'Y'"
* @insert false
*/
property char active;
 
/**
* @fieldtype one-to-many
* @cfc User
* @fkcolumn userid
* @lazy true
* @cascade all
* @inverse
*/
property users;
 
}

Here ‘active’ is the property that is generated by DB and the application calls EntityReload, so that all the property values including ‘active’ are fetched and populated in the object.

There are two issues here

  • EntityReload is getting called immediately after the insertion which is completely unnecessary in this case. All we need here is to get the generated value from the database and you can do that by specifying ‘generated’ attribute on the property. This will tell hibernate that active property is generated by database at the time of insertion and thus suggests hibernate to fetch the value of ‘active’ property from DB right after the row is inserted. When the object is persisted in the DB, the value for ‘active’ property will be populated back in the object immediately. This will save all the overheads of EntityReload.
  • Notice the value for cascade here – it is ‘all’. This means that all the operations, including EntityReload, will be cascaded to the association. Thus all the associated objects will get reloaded irrespective of whether the association is lazy or not. And that is not all – If the associated objects has further associations with ‘cascade’ set on them, the operation will be cascaded on them as well. As a result, the whole object graph will get loaded irrespective of the lazy value on the relationship and that is so so expensive.

The lesson here is not to use EntityReload unless it is necessary. And if you need to use it, check if you really need to cascade this operation to the association. Whenever you specify the cascade value for the association, think about the operations that need to be cascaded and then specify only those values that apply. The valid values for cascade are – save-update, delete, refresh, delete-orphan, merge, all, all-delete-orphan. This is how they map to the operations

cascade value Function
save-update EntitySave
delete EntityDelete
refresh EntityReload
merge EntityMerge

Here is how the CFC looks after fixing these two issues.

/**
* @persistent
*/
Component Group
{
/**
* @fieldtype Id
* @generator native
*/
property id;
 
property name;
 
/**
* @dbdefault "'Y'"
* @generated insert
*/
property char active;
 
/**
* @fieldtype one-to-many
* @cfc User
* @fkcolumn userid
* @lazy true
* @cascade "save-update,delete,merge"
* @inverse
*/
property users;
}