Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of creating objects in ColdFusion

Tags:

coldfusion

At one time I had a theory that instantiating objects on every request rather than having them reside in the Application scope was a huge memory hog. As my knowledge of ColdFusion has grown over the years, I don't think I really understood how CF deals with classes in the "black box" of the CF framework, so I'm going to ask this for community correction or confirmation.

I'm just going to throw out what I think is happening:

  1. A CFC is compiled into a class, each method within that CFC is compiled into a class.
  2. Those classes will reside in (PermGen) memory and can be written to disk based on CF administrator settings.
  3. When a new object is created or template requested, the source code is hashed and compared to the hash stored with the compiled class.
    1. If there is a match, it will use the compiled class in memory
    2. If the compiled class doesn't exist, it will compile from source
    3. If the compiled class exists, but the hash doesn't match, it will recompile.
  4. As an aside, whenever you enable trusted cache, ColdFusion will no longer hash the source to check for differences and will continue to use the compiled class in memory.
  5. Whenever you create a new object, you get a new pointer to the compiled class and its methods' classes and any runtime events occur in the pseudo-constructor. Edit: At this point, I'm referring to using createObject and having any "loose" code outside of functions run. When I say pointer, I mean the reference to memory allocated for the object's scopes (this, variables, function variables).
  6. If you request an init, then the constructor runs. The memory consumed at this point is just your new reference and any variables set in the pseudo-constructor and constructor. You are not actually taking up memory for a copy of the entire class. Edit: For this step I'm referring to using the new operator or chaining your createObject().init() old school.

This eliminates a huge fallacy that I, personally, might have heard over the years that instantiating large objects in every request is a massive memory hog (due to having a copy of the class rather than just a reference). Please note that I am not in favor of this, the singleton pattern is amazing. I'm just trying to confirm what is going on under the hood to prevent chasing down red herrings in legacy code.

Edit: Thanks for the input everyone, this was a really helpful Q/A for me.

like image 393
J.T. Avatar asked Jul 08 '14 18:07

J.T.


People also ask

How do you create a object in ColdFusion?

You use the cfobject tag or the CreateObject function to create a named instance of an object. You use other ColdFusion tags, such as cfset and cfoutput, to invoke the object properties and methods. Many of the techniques for creating and using objects apply to both COM and CORBA objects.

What is the process of creating objects?

The process of creating an object is called Instantiation.

Is ColdFusion object oriented language?

ColdFusion Components (CFCs) CFCs provide some (not all) of the typical features and functionality that are provided by object-oriented (OOP) languages.

How do you check data type in ColdFusion?

CFML is dynamically typed, so types can change as required. You can see the current (JVM) type of a variable by doing <cfdump var=#getMetadata(var)# /> or simply by accessing getMetadata(var). getName() .


1 Answers

I've been developing CF for 14 years and I've never heard anyone claim that creating CFC instances on each request consumed memory due to class compilation. At the Java level, your CFML code is direct compiled to bytecode and stored as Java classes in memory and on disk. Java classes are not stored in the heap, but rather in the permanent generation which is not (usually) a collected memory space. You can create as many instances of that CFC and no more perm gen space will be used, however heap space will be allocated to store the instance data for that CFC for the duration of its existsance. Note, open source Railo does not use separate classes for methods.

Now, if you create a very large amount of CFC instances (or any variable) for that matter, that will create a lot of cruft in your heap's young generations. As long as hard references are not held after the request finishes, those objects will be cleared from the heap when the next minor garbage collection runs. This isn't necessarily a bad thing, but heap sizes and GC pauses should always be taken into account when performance tuning an application.

Now, there are reasons to persist CFC instances, either as a singleton pattern or for the duration of a session, request, etc. One reason is the overhead of actual object creation. This often involves disk I/O to check last modified times. Object creation has increased speed significantly since the old days, but is still pretty far behind native Java if you're going to be creating thousands of instances. The other main reason is for your objects to maintain state over the life of the application/session/request such as a shopping cart stored in session while the user shops.

And for completeness, I'll attempt to address your points categorically:

  1. For Adobe CF yes, for Railo, methods are inner classes
  2. Yes.
  3. Actually, I don't believe there is any hashing involved. It's all based on the datetime last modified on the source file.
  4. Yes, but again, no hashing-- it just skips the disk I/O to check the last modified datetime
  5. I don't think "pointer" is the right term as that implies the Java classes actually live in the heap. CF uses a custom URL classloader to load the class for the template and then an INSTANCE of that class is created and stored in the heap. I can understand how this may be confusing as CFML has no concept of "class". Everything is simply an instance or doesn't exist at all. I'm not sure what you mean by "runtime events occur[ing] in the pseudo-constructor".
  6. To be clear, the JAVA constructor already ran the instant you created the CFC. The CF constructor may be optional, but it has zero bearing on the memory consumed by the CFC instance. Again, I think you're getting unnecessarily hung up on the pseudo-constructor as well. That's just loose code inside the component that runs when it is created and has no bearing on memory allocated in the heap. The Java class is never copied, it is just the template for the instance.
like image 150
Brad Wood Avatar answered Sep 17 '22 16:09

Brad Wood