ColdFusion Dynamic Function Invocation Methods
Tonight I was working with a project that a buddy and I are doing on the side in an attempt to make money and I’m reviewing the code he’s got so far to make sure I have a good grasp on everything that’s going on. He’s built his own ColdFusion framework, and it appears pretty solid, if not a bit heavy. As I’m reviewing this code, however, I see that part of the routing code (yes, it’s an MVC framework) is using evaluate to dynamically execute methods. Although I see why this is happening, I’ve always assumed that evaluate was evil. My first thought was “Why isn’t he using CFINVOKE?”. My second thought was “But is that really better??”
Being the curious guy that I am I decided to make a very unscientific test where I would run two sets of code. The first set determines how much time it takes to create an object using createObject, then call a method against that object 100 times using evaluate. For example,
1 | <cfset evaluate("someObject.#dynamicName#()") /> |
The second set determines how much time it takes to execute a method 100 times using just plain old CFINVOKE.
I ran each test 10 times with the following results:
- Evaluate: average of 267ms
- CFINVOKE: average of 284ms
The small margin of difference did catch me off guard, as I kind of expected CFINVOKE to perform badly, and evaluate to do much better, even though it is evil.
Then I thought, “How about we create the object, then create a reference to the method?” So something like this.
1 2 3 4 5 6 7 8 9 | <cfset start = getTickCount() /> <cfset functionName = "test" /> <cfset o = createObject("MyObject").init() /> <cfset ptr = evaluate("l.o1.#functionName#") /> <cfloop from="1" to="100" index="l.i"> <cfset ptr() /> </cfloop> <cfset end = getTickCount() /> |
I ran this 10 times, and got an average of 15.5ms. WOAH!!! Big difference! So there ya go! Remember that ColdFusion is built on Java, and references are a powerful feature! Happy coding!





You should be aware however, that while CF functions are first class citizens, they don’t retain their context.
That means that if your function ‘test’ in your last code block requires other functions/variables inside your object, it will fail, as it’s current context is your page.
This does mean that you can do some funky things moving functions around, but you need to be careful where you move them to, because depending on context, they will access different data.
Can you give me an example of how you mean? Would the method not have a full context setup in the instantiated object? Perhaps a small example to clarify for me?
Adam,
What big Mark is saying is that in your second test code, the ptr() method is not executing as a method ON the object, “o”. Rather, it is just executing as a UDF defined in the current page. So, if the body of ptr() had a reference to something like:
… likely, you’re test code would throw the error, “Foo id not defined in the current page,” since the execution loses its binding to the object.
Ahhh, I see. And is this due to how CF is invoking methods? I’m pretty sure that CF doesn’t make CFCs into POJOs, and so I’m kind of assuming that invocation is done through reflection, or some other method? Interesting.
@Ben – ‘big Mark’? Now you’re making me blush ;o)
@Adam – CFC methods are actually compiled into their own Java classes. This is why they can be moved around in the way that they are (and also why the more methods a CFC has, the slower it is to instantiate).
Regardless of whether you create a UDF of a page, or in a CFC, it’s actually exactly the same. It just references whatever context it is in – either the page, or a CFC, or another CFC (if you move methods all over the place).
Big Ben hit the nail on the head with his explanation
D