Mach-II: My Final Words

I've been a little gun shy about posting recently. I stopped responding to a post about the use of the This scope. I did not follow up on the arguments for/against my actions with Mach-II. I did not follow up on anything because I got some rather negative feedback from people I respect. Their main argument basically came down to me looking bad because I was advocating altering a framework for perceived optimization.

This is my response on the matter, and if it gets me into more trouble, then so be it. The client I was working for was moving from ColdFusion to ASP. They were running on ColdFusion MX 6.1 and were not going to upgrade. They had a Mach-II application that had 363 method calls per page (213 mach II and 150 non-Mach II), which should not be the case. They were experiencing a HUGE delay per page for more than one or two people at a time and needed it fixed NOW. Yes, I altered Mach-II, along with other code, and it had a positive effect.

Were the number of method calls normal for a Mach-II application? Probably not. If any application used that many method calls, the writer would be shot, so this had to be an abnormal case. Would my alterations show any real speed increase in a well-designed Mach-II application? Again, probably not. I expect that a well-designed Mach-II application would use far fewer method calls and the total savings from the changes I made should be negligable. There are still a few places in Mach-II where I see possible improvements, and these have been sent to the Mach-II team for official review and inclusion. Will they have significant savings? See my answer above.

In the case I mentioned above, the client was happy and the contract was fulfilled. Would I do it again? Definitely! Why?

Because I'm an employee. So are you. We work for someone. We can offer our suggestions to them, let them know what we've seen and heard and try to move them towards proper code and procedures, but at the end of the day we are just employees. The client is always right, and if we feel otherwise, we can either suck it up or get a new client.

I get called in on emergency contracts all the time. When something is going wrong and it needs to be fixed immediately, then I get the call. For the client mentioned above, it required a fast and dirty fix. For another client, it required a fast fix for their "memory build and crash" problem and then an analysis of how to fix it. Sometimes the analysis leads to suggestions that 'break' OOP, but the end result is always the same. Better code for better performance.

Do I disrespect frameworks? Not at all. I'm one of the founders of the Fusebox framework (a methodology at the time). Do I advocate altering frameworks directly? My last post stated quite clearly that I do not feel that a framework should be altered except by those that know what's going on. On the other hand, if you know what's actually happening in the framework, feel free to alter it. But if you do, realize that you are essentially "forking" the framework, and any upgrades made to the framework cannot be reflected in your code unless you make some hands-on alterations.

But that's the beautiful thing of open source. Anyone can fork it. Anyone can remove the parts they don't want or need in order to tailor the code to their use.

What I did to Mach II

There has been a lot of interest in the steps I took to optimize my client's website. The main interest was in what I did to Mach II in order to speed it up, especially as Mach II is rather optimized to start with. The answer is to cheat.

If you look at the Mach II code you'll see that it's rather complex. It's also 1000% legal. Every component is documented as is every cfcomponent and cffunction tag. Output="False" is used everywhere needed, access is always defined, every cffunction tag has a returntype and every cfargument tag has both a type and a required when needed. It is this attention to detail and legality that gives Mach II and every other CFC based framework it's unexpected overhead.

Let's start with the cffunction tag. The returntype attribute performs a data validation on the information being returned from the function. Any validation operation has a certain amount of overhead and when the validation is done against a component reference then the overhead becomes more noticable. In addition, I find the returntype to almost be an insult. If I wrote the function then I should have a relative clue as to what it is returning. If the returntype is only being used for documentation rather than for actual validation, then that information can be put in the hint.

But wait! I'm not saying to remove the returntype. It is actually rather important to the operation of a function. What it does beyond data validation is tell ColdFusion IF the function is returning anything. For this reason I always have a returntype defined but its value will either be any or void. Any basically tells ColdFusion that the function is returning something but that it should not worry about validating it. Void tells ColdFusion that the function will not return anything at all. If a cfreturn tag is used within the function then an error is thrown.

Original cffunction tag
<cffunction name="getDefaultInvoker" access="public" returntype="MachII.framework.ListenerInvoker" output="false" hint="Returns an instance of the default invoker (EventInvoker) for this Listener.">


Modified cffunction tag
<cffunction name="getDefaultInvoker" access="public" returntype="any" output="false" hint="(MachII.framework.ListenerInvoker) Returns an instance of the default invoker (EventInvoker) for this Listener.">

The removal of the returntype alone causes a noticable speed increase for components that are heavily used. If we take the same idea of removing data validation and apply it to cfargument tags then we'll see even more of an improvement. There are actually 2 different types of data validation going on in a cfargument tag. The first is the same data type validation as defined above and this is defined by the type attribute. The second is a check for existance and is defined by the required attribute. The total removal of both of these attributes increases the savings we get from the removal of the returntype. I do one additional thing, though. I add a hint attribute to the tag, which will tell me what data type was expected and if it was required. This is for documentation purposes only, but does help when debugging.

Original cfargument tags
<cfargument name="eventName" type="string" required="true" />
<cfargument name="eventHandler" type="MachII.framework.EventHandler" required="true" />
      

Modified cfargument tags
<cfargument name="eventName" hint="(required - string) what the data should be" />
<cfargument name="eventHandler" hint="required - component) MachII.framework.EventHandler being passed in" />

The removal of the type and/or required attributes from the cfargument tags is not without consequences. There are times where a function needs to be sure of the data being passed in. I judge these on a case by case basis, but when it comes to Mach II I didn't even bother. Mach II is so solid in its construction that every function is very exact in what gets passed to and from it.

As a final warning, remember that Mach II is a closed system that has been heavily tested and is only modified by a select few. No one is supposed to be touching the core code other than those select few. Because of this strict control, I felt very confident in my alterations and they worked flawlessly. In the end thats all that matters to a client...has the job been done.

I don't hate Mach II

I was doing a remote presentation last night on "Object Orienter Programming for ColdFusion Developers" and it eventually moved over to the topic of optimizing ColdFusion Components. While I was showing what I do for speed, I relayed a story about a client of mine who is using Mach II. I was brought in to speed up the clients site which was timing out on a regular basis.

After a review, I found some places that could be optimized and one major place was the Mach II code. I rebuilt most of it and the time savings was immense. Of course, in order to make it faster I had to cheat and break many of the accepted 'rules' of OOP and CFCs. Not something that I suggest anyone doing without a full understanding of the how and why of it (which I'll talk about another time).

After telling the story and showing what I did, someone assumed that I did not like Mach II and asked what Framework I used. I quickly corrected his conclusion and told him not only do I have nothing against Mach II, but it's a really well thought out and solid framework. I don't use it because I don't use any of the public frameworks. I'm obsessed with optimizing my code for speed and performance and really optimal code doesn't go hand in hand with frameworks. On the other hand, I stressed that using a framework is a MUST in almost all situations and that people should not go my route unless they really know what they're doing and have very strict control over who has access to their code.

Bottom line is that unless your a paranoid, obsessive, hermit programmer, use a framework!

FAQ-U 2 - OOP for CF and Frameworks

Yep, the second issue of the Fusion Authority Quarterly Update is not only in my hand, it's packed and ready to go to all subscribers. But of course, anyone who subscribes before the end of the year gets this issue as well as the previous one in PDF format as well. Trust me, PDF is nice to read once in a while, but nothing beats the solid feel of this journal.

As for content, we're talking an actual book worth of Object Oriented Programming for ColdFusion as well as Frameworks. 120 pages of it to be exact (20 pages over what we expected for this issue). But why listen to me when the table of contents speaks for itself:

Editorial

OOP in Your Toolbox
by Judith Dinowitz

Columns

What's Hot? What's Not?
by Raymond Camden, Simeon Bateman, Charlie Arehart, Kurt Wiersma, Michael Dinowitz
Tipical Charlie - How do I Call Thee (CFC)? Let Me Count the Ways!
by Charlie Arehart

Features

Object-Oriented Programming: Why Bother?
by Brian Kotek
The Object-Oriented Lexicon
by Hal Helms
Design Pattern Safari
by Peter J. Farrell
From User-Defined Functions to ColdFusion Components
by Michael Dinowitz
Base Classes: Better Than Your Knew!
by Peter Bell

Concepts

Introduction to Frameworks
by Jared Rypka-Hauer
Fusebox 5 Fundamentals
by Sean Corfield
Mach-II Fundamentals
by Matt Woodward
Model-Glue Fundamentals
by Joe Rinehart
Lessons I Learned from My First Model-Glue Application
by Jeffry Houser
ColdSpring Fundamentals
by Chris Scott
Reactor Fundamentals
by Doug Hughes

Tools

FusionDebug Explained: Interactive Step Debugging for CFML
by Charlie Arehart

And no, we're not going to kill you with advertising. We don't even have advertisers. What we have are supporters who are helping to make sure that we can get the journal to you. A big thanks to:

Adobe Systems, inc. - Makers of ColdFusion, Flex and much, much more

Intergral Information Systems - makers of Fusion-Reactor and Fusion-Debug

WebApper Services, LLC- Makers of SeeFusion

Quill Design - Maker of the SiteDirector shopping system

Straker Interactive - Makers of ZoomFlex

Liquid Image Studios - More creative design than you can shake a forest at

House of Fusion - Providers of quality ColdFusion and related technical content

You can order the journal right away and we'll not only get it to you ASAP but we'll give you access to a PDF of it to hold you over.

http://www.fusionauthority.com/quarterly

We accept orders through Google Checkout (USA Only - Preferred method), Paypal (World wide), or contact us for bulk orders and we'll work with you.

BlogCFC was created by Raymond Camden. This blog is running version 5.9. Contact Blog Owner
House of Fusion | ColdFusion Jobs @ House of Fusion | Fusion Authority