There are a few common reasons given whenever a company says they don't want to use ColdFusion or a developer says "Oh, ColdFusion isn't a REAL programming language". One of these claims is that ColdFusion can't handle large scale enterprise applications. The majority of ColdFusion developers, especially the fanboys, immediately take offense and dive into a passionate discourse on the merits of ColdFusion, blah, blah, blah. I've done my fare share of CF-Evangelism over the years, and I do still believe that the merits of the platform make it a great solution a lot of the time... but I'm much more technology-agnostic these days than I was in my youth, and as I fall in love with other languages because of their merits, I find myself reflecting and sometimes re-evaluating my feelings about ColdFusion. In this entry I'd like to share my thoughts about CF: the good and bad, some advice for developers and companies, and some stories about recent real-world experiences I've had.
The Good There are some things that make ColdFusion a terrific platform. Deployment is a breeze compared to most other programming languages. CFML is not a perfect language, but it is a simple language that makes most programming tasks easy to tackle. This tends to make rapid development easier to accomplish and lends itself particularly well to iterative, agile development practices and all that comes with it (like refactoring). This, coupled with the server error reporting and a few programming language constructs, also means that debugging ColdFusion applications is relatively painless and quick compared to other languages. Speaking directly to the questions of performance and scalability, it is possible to write applications that perform very well and scale exceptionally well with ColdFusion. For example, we (at
Nylon Technology) recently successfully developed and deployed a large scale content management system across multiple servers and server instances. This CMS manages gigabytes of content (tens of thousands of pages) and has a lot of remarkable features (workflows, a robust permissions based security API, etc.).
The Bad There are a few negatives about ColdFusion that should not be ignored. ColdFusion and CFML's ease of use means that you don't have to be a rocket scientist to use it. As I said, this is a strength, but it is also a weakness. There are far too many poorly developed CF applications "in the wild" and far too many "ColdFusion Developers" aren't good "Software Developers". I'm not saying all developers should have a degree in computer science, but more CF Developers should have a better understanding of the ramifications of the code they write, the limitations of the environment they're writing software in, and how to design ("architect") and develop applications that are not just modular, but easy to read, maintain, and extend. Sub-par programmers and poorly written applications will give any programming language a bad reputation. Coupled with the relatively small pool of available talent, it's no wonder some companies want to shy away from ColdFusion, is it?
So let's assume that good developers do create a well-written Enterprise ColdFusion application and have tweaked the hardware and JVM so that they know those won't factor-in as negatives - will it scale and perform well? The three second answer is "maybe... it might and it might not".
The Adobe ColdFusion Application Server is a commercial product and, as such, is a "black box". You write your code and save it somewhere that CF can see, and it "does it's magic" and spits out the results. If you don't like the results, you can change your code and try again, but you can't change what's inside that black box (i.e. the server internals). The most you can do is optimize the Application Server (CF and J2EE) and runtime (JVM) but not the way the server actually works with your code. This is obviously a problem if it turns out that some built-in ColdFusion function or tag is what's killing performance.
Though our client is happy with the CMS I mentioned earlier, along the way we did encounter several (performance related) stumbling blocks that were not the fault of the hardware or software architecture, but ColdFusion itself. One of the things that the CMS does is work with Objects (CFCs) a lot - and constructing/populating thousands of objects comes at a price. The CMS has a caching architecture that in simple terms boils down to storing CFC instances in a structure, using the ID of the content as the key name. We found that as the number of objects in memory grew, performance crept to a complete stand still - the server eventually died, as more and more threads timed out waiting for the threads that were accessing the structure keys to complete their job. Turns out that not caching the instances was the fix - but why? Because of a bug in ColdFusion that as far as I know, was first reported by David Sheldon on his blog at
http://cfdumped.blogspot.com/2006/09/bad-hash-function-causes-problems-with.html. Maybe this bug doesn't affect the majority of applications, but for applications that need to store a large number of values in a complex data type, structures are not an option. One of the few fundamental data types in CF is broken - that's a big deal. I believe this issue was addressed in a CFMX 8.01 hotfix this year, but I haven't confirmed... and I personally think it's unacceptable for that bug to be made public knowledge and not be fixed for 2+ years.
We recently had another performance related issue with the application. The unique IDs of search results from a SQL statement are stored in a string and that string of IDs persisted and used for pagination. This is necessary because re-running the query isn't an option and storing the entire recordset would use far too much memory. So, the approach is right... but performance is abysmal (to the point that internal server errors are thrown) when lists get large - sometimes they're as large as 150,000+ (remember, this is an enterprise application and we need to work with huge volumes of data). The code that kept crashing looked something like this:
<cfscript>
for(j = 1;j lte listLen(daList);j++){
test = listGetAt(daList,j);
}
</cfscript>
OK, so you're thinking, "Remove the listLen() call from the loop condition" - right? We did, and it got a little better but would still time out sometimes and would be very slow other times. That code looks like:
<cfscript>
tmpVal2 = listLen(daList);
for(j = 1;j lte tmpval2;j++){
test = listGetAt(daList,j);
}
</cfscript>
Turns out that listGetAt() is just a horribly inefficient beast. Temporarily replacing the list with an array and then accessing indeces in the array worked like a charm and made an exponential difference to performance:
<cfscript>
tmpVal3 = listToArray(daList);
tmpVal2 = arrayLen(tmpVal3);
for(j = 1;j lte tmpval2;j++){
test = tmpVal3[j];
}
</cfscript>
The example of listLen() brings up a good question - is there something wrong with that code or is it fair to say that ColdFusion is to blame? Rather than answering directly, I'll describe how I view the roles and responsibilities of CFML and the (ColdFusion) server, as well as my own complaints/disappointments with each. We'll start with the language - CFML. The CFML programming language is not the problem - in fact I think it's a good language (note that by "CFML" I mean "CFML and CFSCRIPT"). When I first heard about the CFML advisory panel, though skeptical, I did think it was a good idea - I still do. However, what I believe we truly need is a real language specification - one that states how the built-in tags and functions are to be implemented. Of course, since Adobe owns the server, though they've put together an advisory board, they have not published the language as a public specification. I would be pleasantly surprised if they did. There are several good examples of how a language specification is implemented and of the benefits that come from a public spec. One example is ANSI SQL - if a vendor says they support it, you are assured that your SQL will work. Another good example is ANSI Common LISP - the specification states exactly what (and in many cases how) vendors must implement the language. If you write your applications in Common LISP, you know exactly what to expect from implementation to implementation. Unlike CFML, for which a public specification could easily be made, the ColdFusion Server is a product owned by an entity and it wouldn't be fair (or make sense) to publish a standard defining how to write the server. Perhaps there is a solution, though. At a high level, the server is responsible for serving two primary functions: it is a compiler and it is a runtime platform. Perhaps it does not make sense to have an open standard that states how the runtime must work internally (beyond a specification for the side effects and behavior of the CFML language constructs), but a specification for how the server works as a compiler, if expressed at the language construct level and as part of a CFML specification, is plausible. For example, in my first list code snippet I pointed out that the listLen() in the for loop condition (for(j = 1;j lte
listLen(daList);j++)) was causing a serious performance problem because it's evaluating on every pass... but there's no reason that the server, when compiling that CFML, couldn't have introspected the contents of the loop and determined that it was safe to compile it as byte code that evaluates a number (instead of the actual expression) on each pass. "Compiler Optimization" is something I've learned a lot about in my continuing education and experimentation with LISP - and it's something that the Adobe Engineering team should be focused on. I'm not saying they aren't (I really don't know) - I know they do focus on making the internal server code faster (the actual tags/functions) and the compilation process faster, but I do not know if they look at ways to optimize the actual results of the compilation process (rather than the code those results executes). A language specification that defines the compiler behavior for some, if not all, of the language would be a huge benefit to all.
The bottom line is that in the Enterprise, ColdFusion absolutely can perform and scale very well - but that no matter how great the hardware, how tweaked the VM and servers, and no matter how well written and well architected the code base, a very resource intensive application may perform poorly for no reason other than what can only be nicely described as "quirks in the server".