Reputation: 1806
We are pulling in hierarchical data into our Coldfusion application and parse it into numerous CFCs. The CFC in question stores an array of its children, which are also instances of the same type of component. Parsing some of this data may lead to having to create 100 or more (the most ever would be like 300) CFCs by the time it is done...
Sometimes, creating all of these CFCs can take only 50-75ms, sometimes it takes 1000-1250ms. (I made a script that loops and just creates and stores these objects, using GetTickCount() to keep track of the speed.) I know server load probably has a lot to do with this, but was wondering if there was some way to improve the performance of creating these objects?
(The first battle was getting all of the data for these objects in one DB call, which we were able to do, but now that runs consistently, we found that instantiating a bunch of these CFCs may also be a bottleneck.)
Upvotes: 1
Views: 1173
Reputation: 9455
The bottom line is that object creation in ACF has always been memory intensive. It's gotten better with ACF9, but not by much. I can guarantee that taking the same code and run it on Railo (you might have to modify it slightly), you will see a HUGE improvement in CFC creation and even memory consumption. This is not to tell you to switch engines for your project, it's just to tell you that if you're using ACF as your engine, you need to rethink your apps' architecture from using too many CFCs.
That said, the first thing to do is ask yourself, do you really need to be creating so many CFCs? As much as people want to believe that CFCs are the swiss army knife of CFML, they really are a double edged sword. Though they can encapsulate logic for you, they come with the performance trade off. Very often I've seen data stuffed into CFCs that can be rewritten to use arrays and structs to represent the data structure.
So in your case, rather then hitting your head against the wall with trying to get ACF to do something that it will never do (object creation efficiently), I would look at reworking the code to use arrays and structures and only use CFCs when absolutely necessary.
Upvotes: 2
Reputation: 565
One option would be to refactor your code to do the following: utilize CFCs on create and update functions (where persistence is required) and utilize structures on reads. It is much less expensive to create a structure (a hash map) than a CFC.
Your views would almost always then refer to a structure version of an object and its children, while your model would need to handle both the structure version and the CFC version when making attribute calls. This approach results in inconsistent code in how you directly reference a member of an object, but it will be significantly faster than trying to create hundreds or thousands of CFCs at once.
Upvotes: 1
Reputation: 4694
The most efficient thing you can do is not recreate the object on every request. How you go about this depends on the particular use case. One thing that might work for you if you are not dealing with a massive number of unique objects is to have a cache struct in application scope keyed by something like "#tablename#--#primarykey#". When you are about to create an object first check whether the primarykey exists in application scope, if it does then you can just update the data in the object and use it, otherwise create a new object. It is the initial creation of the object that is the most taxing part of the process.
<cfif not structkeyexists(application, "objectcache")>
<cfset application.objectcache = {} />
</cfif>
<cfloop query="children">
<cfif not structkeyexists(applicatin.objectcache, "childtable--#ID#")>
<cfset application.objectcache = createobject(...).init(...) />
</cfif>
<cfset arrayappend(variables.instance.children, application.objectcache["childtable--#ID#"]) />
</cfloop>
You might also want to throw a cflock around the code to prevent issues. If you do have a large number of objects this can still be helpful as you could cache the 10,000 most recent by using a date flags in the object or in another struct.
Upvotes: 3