Skip to main content
BreakawayPaul
Inspiring
December 17, 2011
Question

cfinvoke vs createobject

  • December 17, 2011
  • 4 replies
  • 7924 views

I have a bunch of web apps that use <cfinvoke> statements to call CFCs.  After a recent CF Server Admin class, our instructor mentioned that <cfinvoke> was VERY slow, and that I should be using CreateObject() instead, because it's more efficient.

So my question is, has anyone done any comparisons to see the actual difference?  I'm curious to hear other people's experiences with this.

    This topic has been closed for replies.

    4 replies

    BreakawayPaul
    Inspiring
    December 20, 2011

    Thanks for all the replies everyone.  It was really helpful and interesting!

    Inspiring
    December 17, 2011

    I'm with Dave on this one.

    Creating an object and reusing it (which one can just as much do with <cfinvoke> as one can with createObject(), btw, provided one has a constructor method in one's CFC) is going to be more efficient than using a transient object every time one wants to use a method of that CFC.  But there's nothing inately slower in using <cfinvoke> than createObject(), as far as I know.  However I'd want to load test both solutions before making a concrete claim on that.

    The "default" approach with <cfinvoke> is to create transient objects every call, so using that approach will have that overhead each time.  However one does not need to create a transient object every time with <cfinvoke>.

    Here's code demonstrating like-for-like approaches with both <cfinvoke> and createObject():

    <!--- transient objects --->

    <cfinvoke component="MyCfc" method="f" result="resultOfF">

    <cfinvoke component="MyCfc" method="g" result="resultOfG">

    <cfinvoke component="MyCfc" method="h" result="resultOfH">

    <cfset resultOfF = createObject("MyCfc").f()>

    <cfset resultOfG = createObject("MyCfc").g()>

    <cfset resultOfH = createObject("MyCfc").h()>

    <!--- persistent object --->

    <cfinvoke component="MyCfc" method="init" result="myObject">

    <cfinvoke component="#myObject#" method="f" result="resultOfF">

    <cfinvoke component="#myObject#" method="g" result="resultOfG">

    <cfinvoke component="#myObject#" method="h" result="resultOfH">

    <cfset myObject = createObject("myCfc").init()><!--- NB: even calling it without the init() will return an object instance, but I want to keep both bits of code as similar as possible --->

    <cfset resultOfF = myObject.f()>

    <cfset resultOfG = myObject.g()>

    <cfset resultOfH = myObject.h()>

    I would expect the different syntactical approaches for transient objects to perform about the same, and again, either syntax for persistent objects would perform about the same.

    My reason for using createObject() over <cfinvoke> is that I don't see why I'd want to use a special tag just for creating and using objects.  It makes much more sense to just use <cfset>.  I really don't know why <cfinvoke> was ever added to the language.

    Also note that the reason one might use a transient or a persistent object should not be down to the calling syntax, it should be down to the purpose and implementation of the component.  There will be reasons to use transient objects, and reasons to use persistent objects, but the calling syntax should not dictate the usage here.

    --

    Adam

    Community Expert
    December 17, 2011

    My reason for using createObject() over <cfinvoke> is that I don't see why I'd want to use a special tag just for creating and using objects.  It makes much more sense to just use <cfset>.  I really don't know why <cfinvoke> was ever added to the language.

    My guess as to why it was added is that there are enough cases where it doesn't make sense to keep a reference around, such as web service calls, and that you can easily generate code for a tag rather than for an expression. For example, in Dreamweaver you can drag a method of an object or web service into your code, and it generates a CFINVOKE tag for you. That's just a guess, though.

    Dave Watts, CTO, Fig Leaf Software

    Dave Watts, Eidolon LLC
    BreakawayPaul
    Inspiring
    December 17, 2011

    Did your sodas stay safe, Dave?

    Using BKBK's script, I got this:

    createobject execution time: 30

    cfinvoke execution time: 20

    The CFC just did a select from a tiny database and cfdumped the results, so it's not much of a load.

    This was CF9 and MySQL on Ubuntu 10.10 (my local machine).

    cfinvoke seems to be faster, but perhaps it hogs more resources?

    Interesting!

    BKBK
    Community Expert
    Community Expert
    December 17, 2011

    BreakawayPaul wrote:

    I have a bunch of web apps that use <cfinvoke> statements to call CFCs.  After a recent CF Server Admin class, our instructor mentioned that <cfinvoke> was VERY slow, and that I should be using CreateObject() instead, because it's more efficient.

    There is very little justification for you to make a general comparison between cfinvoke and createobject on the basis of speed or efficiency. They are 2 different things. In fact, I will now present arguments showing that, in some ways, cfinvoke is the more efficient. 

    To compare like with like, you have to compare cfinvoke with the following 2 actions: 1) instantiation with createobject; 2) invocation of a method on the object created in 1).

    Cfinvoke creates an object and invokes a method in one go. There is then an infinitesimal time gap between the two actions. Whereas, createobject may involve an arbitrary amount of latency. If you create an object with createobject, and then invoke a method on the object later in the code, the time gap between the two actions can be arbitrarily large.

    Moreover, cfinvoke instantiates the component transiently (that is, the resulting object is not serializable). The object you instantiate with createobject is serializable which, I would imagine, requires more overhead in terms of CPU resources.

    Inspiring
    December 17, 2011
    Moreover, cfinvoke instantiates the component transiently (that is, the resulting object is not serializable). The object you instantiate with createobject is serializable which, I would imagine, requires more overhead in terms of CPU resources.

    The reason a transient object - in the example of using one with <cfinvoke> - isn't serialisable is because one never actually gets given an object reference to then use in the objectSave() call.  It's got nothing to do with whether the object reference is created using either <cfinvoke> or createObject(), it's that there is no object reference at all.  Transience is the lack of a reference being created (and all the knock-on effects that has, one of which the object can't be serialised); the inability to serialise the object is just a symptom of that.

    --

    Adam

    BKBK
    Community Expert
    Community Expert
    December 17, 2011

    Adam Cameron. wrote:

    Moreover, cfinvoke instantiates the component transiently (that is, the resulting object is not serializable). The object you instantiate with createobject is serializable which, I would imagine, requires more overhead in terms of CPU resources.

    The reason a transient object - in the example of using one with <cfinvoke> - isn't serialisable is because one never actually gets given an object reference to then use in the objectSave() call.  It's got nothing to do with whether the object reference is created using either <cfinvoke> or createObject(), it's that there is no object reference at all.  Transience is the lack of a reference being created (and all the knock-on effects that has, one of which the object can't be serialised); the inability to serialise the object is just a symptom of that.

    Adam, you misunderstand my logic. Your counterargument therefore fails to counter my argument.

    Reread what I wrote. I used 'serializable' to illustrate my point, my point being "cfinvoke instantiates the component transiently".

    Community Expert
    December 17, 2011

    My understanding is that this is a bit of an oversimplification, and depends on how people usually use CFINVOKE and createObject. The efficiency comes by instantiating an object and keeping it around in memory, rather than reinstantiating it every time it's needed. By default, when you use CFINVOKE, that's how it works. When you use createObject, you can choose whether you want to store an object reference in a variable a bit more naturally, so people are more likely to do that. But it is possible to create an object reference with your first CFINVOKE, then use subsequent ones to refer to that reference if you really want to.

    All that said, I think you're better served by using createObject for this, as it's a more intuitive syntax for manipulating objects - or at least, it's more sensible if you're coming from other programming languages.

    Dave Watts, CTO, Fig Leaf Software

    Dave Watts, Eidolon LLC