Monday, February 28, 2011

Using the Java StringBuilder Class to Increase ColdFusion String Performance

One of the commonly known best practices in Java programming is to use the java.lang.StringBuilder class (read more here) when you are doing a lot of string concatenation operations.  The reason is because Java String (and by association ColdFusion strings) objects are immutable, which means that once a String is created its internal state is unchangeable.  So this means that every time you are changing a string, Java is actually creating a new string object behind the scenes and re-assigning it to your variable.  This got me thinking about the performance implications of using the StringBuilder class in my ColdFusion applications.

For this test I created two templates, one using the & operator to construct a large string and the other using the StringBuilder class to do the same operation.  Below is the code from both of the files (with most of the test text removed however I used the exact same text string for both files):

Using the & operator:

<cfscript>
 writedump(NOW());
 
 stop = false;
 
 myAppendedText = "";
  
 myText = "Lorem ipsum dolor sit amet, ...";
 
 myWordArray = listToArray(myText," ");
 
 for(i =1; i <= 2500; i++){
  
  myAppendedText &= myText;
 }
 
 writedump(NOW());
</cfscript>

Using the StringBuilder class:

<cfscript>
 writedump(NOW());
 
 stringBuilder = createObject("Java","java.lang.StringBuilder");
 
 stop = false;
 
 myAppendedText = "";
  
 myText = "Lorem ipsum dolor sit amet, ...";
 
 myWordArray = listToArray(myText," ");
 
 for(i =1; i <= 2500; i++){
  
  stringBuilder.append(myText);
 }
 
 writedump(NOW());
</cfscript>

The results were quite convincing.   Using the & operator the script ran in 23 seconds, the template using the StringBuilder object ran the code in under 1 second.  So the next thing I wanted to do was to see how well the ScriptBuilder method would scale so I increased the number of times the loop ran that added text to 5500 and the ScriptBuilder method still ran in under a second!

The moral of the story is that if you have to do lots of string concatenation the clear choice is to use the StringBuilder class.  I do stress that the effectiveness of this method only works under situations where you are doing A LOT of string concatenation.  The performance difference between the two methods was very minimal until I started to create some pretty big strings, but once I hit that threshold the StringBuilder significantly outperformed using the & operator.

Tuesday, February 22, 2011

Post some CF code on github and win a copy of the ColdFusion Anthology!

Since I'm far too busy to write a meaningful blog this week, so lets have some fun.  I have a brand new copy of the ColdFusion Anthology to give away (it is a copy with the missing chapter but its free so stop being picky).  To enter the contest all you have to do is write some ColdFusion code that will select a random winner from the comments of this post, create a gist for the code on github at https://gist.github.com/ (make sure you select ColdFusion as the language), and patse a link to the gist in the comments of this post. The contest will go through March 20th since its my son's first birthday. 

Since I'm paying for shipping out of my own pocket I can only ship to the Continental United States.  But if you aren't from the Continental US and still want to submit some code, I'd love to see it.  I can still pick you as a winner but the book will have to go to the runner up.  The winner of the book will be chosen by me as the one with the most creative code.  I also have a few hard copies of the ColdFusion 9 refcardz by Terry Ryan that I'll send to a few of the people chosen by the code that was submitted. 

Monday, February 14, 2011

What I Learned at the Milwaukee Hack-a-thon

This past weekend I participated in my first hack-a-thon put on by Spreenkler Talent Labs.  My team consisted of myself and 3 other developers: my good friend Ryan Nanney who is a php developer, Joe Steinbring who is a fellow ColdFusion developer, and Russel Stetzer who is a networking guy looking to break into the development side of things.


As this was my first hack-a-thon event I wasn't sure what to expect going in and I was very careful to make sure that my team didn't break any rules by doing any development work ahead of time.  Looking back I think I may have been too careful.  Prior to the event our team only had two short meetings to discuss our idea and go over some of the frameworks and technologies we were planning on using.   So going into the event we knew that we were going to build an application that would help non profits looking for volunteers connect to professionals that wanted to volunteer their time and that we were going to use ColdFusion 9, ColdFusion ORM, FW/1 as our MVC framework, github as our collaboration hub, and jQuery as our JavaScript framework.


The event itself was held in a computer lab at the University of Wisconsin Milwaukee, which proved to be a bit small for the amount of participants that were in attendance.   I'm glad I decided to play it safe and pack up my keyboard, external monitor, and mousepad since I arrived at the about 5 minutes late and all of the spots with monitors already there were gone.  Lucikly two of my team members arrived early and I was able to get a spot right by them.

Once the event kicked off our team got off to a slow start, I think that it was around 12:00 before we actually wrote a single line of code.  The morning was mostly spent getting everybody's development environment up and running and working on the getting the look and feel of our application sorted out.  When we finally started writing code things became quite hectic in a hurry. While we had our team roles pretty clearly defined ahead of time, we didn't have a very good plan on how we were going to actually build this application.  I was to be the guy person in charge of the master branch of the project and wiring up the different layers of the MVC framework,  Ryan N was to work on the CSS and jQuery, Joe was to work on the data model and database, while Russ helped work on the view pages.   



One of the biggest strategical flaws that I helped push was to use a few technologies that every team member wasn't familiar with, specifically ColdFusion ORM and FW/1.  While I felt that these technologies are extremely simply to use and learn, 8 hours just isn't enough to teach 3 people to use them and be productive myself. 

By the end of the day we had written a lot of code, however our application was quite disjointed and wasn't quite what we had envisioned for the application.   Even though I wasn't completely thrilled with our final product I can say that I had so much fun at this event that it didn't matter.  I also learned a lot of things that I'll put in practice at the next event because I definitely plan on doing this again.  After a little reflection this is what I learned for the next hack-a-thon:

Have all software installed before the event.
First and foremost make sure that every team member has all the software needed before the event, time is of the utmost importance and you don't want to waste it downloading and installing software.  

Don't be over ambitions with your application.
Just as important as being prepared make sure that you have an idea in mind that can be executed in such a short time frame.  The application you develop for an event like this should be extremely simple, I'd say no more than 2-3 screens max with an equally simple data model.  

While we felt that the application was simple enough before hand, we quickly realized that this application would need 4 or 5 distinct areas, each with its own set of screens and database tables.  This is far too many when you are trying to deliver a complete application in less than 8 hours.

A hack-a-thon is not a time to teach and learn new technologies
While my goal going into this even was to show people how great ColdFusion, ORM, and FW/1 were there just isn't enough time to teach, learn, and execute.  While I did succeed in wowing my team members with the capabilities of ORM and FW/1 too much valuable time was spent teaching and learning when we needed to be executing. 


Break free of your "enterprise" or "corporate" practices. 
When I first sat down to start coding I envisioned writing the elegant API with a very clean and nice separation of concerns in the MVC layer. I think at one point I even was going to thrown in a unit test or two???  What was I thinking??  This is a HACK-a-thon, hack the thing together and make the code pretty later.  Heck it ended up a mess anyway, I might as well have just started out throwing code together saved the time putting together a nice folder structure and object structure.  Since there is no shame in my game if you want to see what we pumped out in 8 hours the code is all up at github here: https://github.com/bittersweetryan/Waternoose.

While I wish our team could have represented ColdFusion a bit better I came away learning some valuable lessons that I will apply in the next event.  On top of all of that I also got a $10 iTunes gift card, the Xbox 360 game "Allen Wake", and a "Make Web not War" t-shirt.  All-in-all not too shabby for a Saturday.  I can't wait for the next one!

Wednesday, February 9, 2011

Using Metadata To Add Static Variables to ColdFusion Components

Let me start out by saying that everything in this this post I learned from Elliot Sprehn's fantastic CFMeetup presentation "I bet you didn't know you could do that with ColdFusion".  If you haven't already seen this presentation, you should.  Even if you have seen it you should watch it again, and show it to anyone you know who loves to bash ColdFusion.   Anyways, I wanted to play around with this concept on my own to see how I could get it to work for me.  

First, if you are unfamiliar with the concept of metadata in ColdFusion read "Using introspection to get  metadata for components" at adobe.com on for some background.  Also should check out the getMetaData and getComponentMetaData functions over at CFQuickDocs.  The most important thing to know for this post is that these functions return a structure that describes an object.  These properties are generated the first time an object is instantiated and will persists until the object is recompiled by the ColdFusion server.

So what exactly am I talking about when it comes to adding static variables to ColdFusion components?  Well if anybody has worked with a strongly typed language such as .NET or Java you'll be familiar with the static keyword.  Static variables are variables that are variables that exist in only one place and are accessible without having to instantiate a instance of a object.  Basically you can access a property on an object by calling ObjectName.staticVar without having to create a new ObjectName().

Lets take a look at a bare bones component called Employee:

<cfscript>
component name="Employee"
{
 public Employee function Init(){
  var metadata = getComponentMetaData("Employee"); 
  
  if(!structKeyExists(metadata,"myStaticVar")){
   
   lock name="metadata.myStaticVar" timeout="10"{
    metadata.myStaticVar = "Hello Static Variable."; 
   }
  }
  
  return this;
 }
}

As you can see when this component's Init() method is called I get the components metadata and look for a key called "myStaticVar" and if it doesn't exist I create it.  Note: it's important to lock the creation of this key since you are manipulating a shared scope.  Its important to note here that until this component is compiled by ColdFusion this key does not exist.  Dumping the output of getComponentMetaData("Employee")at this point will produce the following output:






















As you can see there is no key for "myStatcVar" which was defined in the init() method of the component.   So let's create an instance of the component and dump its metadata.

<cfscript>
Employee = new Employee();
writeDump(getComponentMetaData("Employee");
</cfscript>
 






















Now you can see that my  the component metadata structure has a key "MYSTATICVAR".  The real beauty of this is that this metadata persists server wide for this component until it is recompiled by the ColdFusion server.   I tested this by creating  a new directory with a new application.cfc and with a new application name and dumped the metadata on the Employee component as shown below:

<cfscript>
writeDump(getComponentMetaData("Employee");
</cfscript>

Sure enough, the MYSTATICVAR key was there.  I even created a completely new website and mapped the component directory to the directory that holds my Employee component and ran the code above again and the metadata was there.

Now anytime I want to access the value of my static variable all I have to do is write code like this to retrieve the value of the static variable:

<cfscript>
 staticVariableValue = getComponentMetaData("Employee").myStaticVar;
 
 writedump(staticVariableValue);
</cfscript>

It's important to note that when the server is restarted this metadata will once again disappear until the component is created for the first time.
Fork me on GitHub