Extending ColdFusion Components And Its Impact On Page Performance

Posted November 8, 2006 at 2:31 PM by Ben Nadel

Tags: ColdFusion

It was lunch time and I was curious as to how extending ColdFusion Components affects page processing time and performance. For those of you who don't know, you can "inherit" the functionality of one component by extending it and overriding functionality. Component instantiation has some overhead in ColdFusion so that leads me to think that using extend has even more overhead... but does it.

To test, I created a Girl.cfc and FullGirl.cfc. The Girl.cfc extends Person.cfc which extends AbstractBaseComponent.cfc. The FullGirl.cfc, on the other hand is "God Object" that can do everything that Girl.cfc does, except that it doesn't need to extend anything.

I then ran tests instantiation X number of components of each type:

  • <!--- Set the test size. --->
  • <cfset intSize = 1000 />
  •  
  • <!--- Create an array for the girls. --->
  • <cfset arrGirls = ArrayNew( 1 ) />
  •  
  • <!--- Resize the array. --->
  • <cfset ArrayResize( arrGirls, intSize ) />
  •  
  •  
  • <!---
  • Test the performance of components that
  • extend other components.
  • --->
  • <cftimer label="Extend Methodology" type="outline">
  •  
  • <!--- Loop over the size and add a girl. --->
  • <cfloop index="intIndex" from="1" to="#intSize#" step="1">
  •  
  • <cfset arrGirls[ intIndex ] = CreateObject(
  • "component",
  • "Girl"
  • ).Init(
  • FirstName = "Yuu",
  • LastName = "Sekine"
  • ) />
  •  
  • </cfloop>
  •  
  • </cftimer>
  •  
  •  
  • <!---
  • Test the performance of the a GOD component that
  • doesn't need to extend anything.
  • --->
  • <cftimer label="God Object Methodology" type="outline">
  •  
  • <!--- Loop over the size and add a girl. --->
  • <cfloop index="intIndex" from="1" to="#intSize#" step="1">
  •  
  • <cfset arrGirls[ intIndex ] = CreateObject(
  • "component",
  • "FullGirl"
  • ).Init(
  • FirstName = "Yuu",
  • LastName = "Sekine"
  • ) />
  •  
  • </cfloop>
  •  
  • </cftimer>

After a few tests of creating 1,000 instances, these are the results that I got:

Using Extended Components

1: 15,937 ms
2: 16,312 ms
3: 16,312 ms
4: 16,312 ms
5: 16,281 ms
6: 15,765 ms
7: 16,171 ms
8: 15,765 ms

Using GOD Components

1: 16,328 ms
2: 15,718 ms
3: 15,718 ms
4: 15,750 ms
5: 15,827 ms
6: 15,765 ms
7: 16,281 ms
8: 16,296 ms

As you can see, over a 1,000 object instantiations, the GOD object creation was only marginally faster. In fact, the GOD object creation was occassionally slower. I would say that this is a totally negligible difference. This is very good to know. Extending components makes code easier to extend and maintain. It's nice to know this can be done without really sacrificing any performance.

If you are interested in seeing the ColdFusion components that I wrote for this, they are listed below.

AbstractBaseComponent.cfc ColdFusion Component

  • <cfcomponent
  • displayname="AbstractBaseComponent"
  • output="false"
  • hint="Handles base functionality for CFCs.">
  •  
  •  
  • <!--- Set unique ID for this instance. --->
  • <cfset VARIABLES.InstanceID = CreateUUID() />
  •  
  •  
  • <cffunction name="Init" access="public" returntype="AbstractBaseComponent" output="false"
  • hint="Returns an initialized AbstractBaseComponent instance.">
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="EqualTo" access="public" returntype="boolean" output="false"
  • hint="Determines if this ">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Comparable" type="any" required="true" />
  •  
  • <!--- Try to compare this object instance to the passed in. --->
  • <cftry>
  •  
  • <!--- Compare this ID to that ID. --->
  • <cfreturn NOT Compare(
  • VARIABLES.InstanceID,
  • ARGUMENTS.Comparable.GetInstanceID()
  • ) />
  •  
  • <cfcatch>
  •  
  • <!--- An error occurred, return false. --->
  • <cfreturn false />
  •  
  • </cfcatch>
  • </cftry>
  • </cffunction>
  •  
  •  
  • <cffunction name="GetInstanceID" access="public" returntype="string" output="false"
  • hint="Returns the instance's unique ID.">
  •  
  • <cfreturn VARIABLES.InstanceID />
  • </cffunction>
  •  
  • </cfcomponent>

Person.cfc ColdFusion Component

  • <cfcomponent
  • displayname="Person"
  • extends="AbstractBaseComponent"
  • output="false"
  • hint="Handles base functionality for the 'person' package of objects.">
  •  
  •  
  • <!--- Set default properties. --->
  • <cfset VARIABLES.Instance = StructNew() />
  • <cfset VARIABLES.Instance.FirstName = "" />
  • <cfset VARIABLES.Instance.LastName = "" />
  •  
  •  
  • <cffunction name="Init" access="public" returntype="Person" output="false"
  • hint="Returns an initialized Person instance.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="FirstName" type="string" required="false" default="" />
  • <cfargument name="LastName" type="string" required="false" default="" />
  •  
  • <!--- Store arguments. --->
  • <cfset VARIABLES.Instance.FirstName = ARGUMENTS.FirstName />
  • <cfset VARIABLES.Instance.LastName = ARGUMENTS.LastName />
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="GetFirstName" access="public" returntype="string" output="false"
  • hint="Returns first name.">
  •  
  • <cfreturn VARIABLES.Instance.FirstName />
  • </cffunction>
  •  
  •  
  • <cffunction name="GetLastName" access="public" returntype="string" output="false"
  • hint="Returns last name.">
  •  
  • <cfreturn VARIABLES.Instance.LastName />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetFirstName" access="public" returntype="void" output="false"
  • hint="Sets first name.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="FirstName" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.FirstName = ARGUMENTS.FirstName />
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetLastName" access="public" returntype="void" output="false"
  • hint="Sets last name.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="LastName" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.LastName = ARGUMENTS.LastName />
  • <cfreturn />
  • </cffunction>
  •  
  • </cfcomponent>

Girl.cfc ColdFusion Component

  • <cfcomponent
  • displayname="Girl"
  • extends="Person"
  • output="false"
  • hint="Handles a Girl object.">
  •  
  •  
  • <!--- Set default properties. --->
  • <cfset VARIABLES.Instance.Gender = "Female" />
  •  
  •  
  • <cffunction name="GetGender" access="public" returntype="string" output="false"
  • hint="Returns gender.">
  •  
  • <cfreturn VARIABLES.Instance.Gender />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetGender" access="public" returntype="void" output="false"
  • hint="Sets gender.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Gender" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.Gender = ARGUMENTS.Gender />
  • <cfreturn />
  • </cffunction>
  •  
  • </cfcomponent>

FullGirl.cfc ColdFusion Component

  • <cfcomponent
  • displayname="FullGirl"
  • output="false"
  • hint="Handles all the girl functionality.">
  •  
  •  
  • <!--- Set unique ID for this instance. --->
  • <cfset VARIABLES.InstanceID = CreateUUID() />
  •  
  • <!--- Set default properties. --->
  • <cfset VARIABLES.Instance = StructNew() />
  • <cfset VARIABLES.Instance.FirstName = "" />
  • <cfset VARIABLES.Instance.LastName = "" />
  • <cfset VARIABLES.Instance.Gender = "Female" />
  •  
  •  
  • <cffunction name="Init" access="public" returntype="FullGirl" output="false"
  • hint="Returns an initialized Person instance.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="FirstName" type="string" required="false" default="" />
  • <cfargument name="LastName" type="string" required="false" default="" />
  •  
  • <!--- Store arguments. --->
  • <cfset VARIABLES.Instance.FirstName = ARGUMENTS.FirstName />
  • <cfset VARIABLES.Instance.LastName = ARGUMENTS.LastName />
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="EqualTo" access="public" returntype="boolean" output="false"
  • hint="Determines if this ">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Comparable" type="any" required="true" />
  •  
  • <!--- Try to compare this object instance to the passed in. --->
  • <cftry>
  •  
  • <!--- Compare this ID to that ID. --->
  • <cfreturn NOT Compare(
  • VARIABLES.InstanceID,
  • ARGUMENTS.Comparable.GetInstanceID()
  • ) />
  •  
  • <cfcatch>
  •  
  • <!--- An error occurred, return false. --->
  • <cfreturn false />
  •  
  • </cfcatch>
  • </cftry>
  • </cffunction>
  •  
  •  
  • <cffunction name="GetFirstName" access="public" returntype="string" output="false"
  • hint="Returns first name.">
  •  
  • <cfreturn VARIABLES.Instance.FirstName />
  • </cffunction>
  •  
  •  
  • <cffunction name="GetGender" access="public" returntype="string" output="false"
  • hint="Returns gender.">
  •  
  • <cfreturn VARIABLES.Instance.Gender />
  • </cffunction>
  •  
  •  
  • <cffunction name="GetInstanceID" access="public" returntype="string" output="false"
  • hint="Returns the instance's unique ID.">
  •  
  • <cfreturn VARIABLES.InstanceID />
  • </cffunction>
  •  
  •  
  • <cffunction name="GetLastName" access="public" returntype="string" output="false"
  • hint="Returns last name.">
  •  
  • <cfreturn VARIABLES.Instance.LastName />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetFirstName" access="public" returntype="void" output="false"
  • hint="Sets first name.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="FirstName" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.FirstName = ARGUMENTS.FirstName />
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetGender" access="public" returntype="void" output="false"
  • hint="Sets gender.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Gender" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.Gender = ARGUMENTS.Gender />
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction name="SetLastName" access="public" returntype="void" output="false"
  • hint="Sets last name.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="LastName" type="string" required="true" />
  •  
  • <!--- Set value. --->
  • <cfset VARIABLES.Instance.LastName = ARGUMENTS.LastName />
  • <cfreturn />
  • </cffunction>
  •  
  • </cfcomponent>


Reader Comments

Nov 8, 2006 at 3:06 PM // reply »
1 Comments

I appreciate you showing this, I always had a nagging voice in my head wondering if my making well structured code was secretly crippling performance. No worries now!


Nov 8, 2006 at 4:25 PM // reply »
56 Comments

@Ben,

I can't stress this enough:

Iteration performance tests are worthless.

If you want a true test to see which is more efficient, then you MUST do a proper load test in a proper environment.

How the hell do you know that a some other process running in the background on your machine interfered with these results? You don't.

I'm sorry it sounds like I'm yelling at you, but I can't stand the fact that every single person in the CF community thinks that writing a loop constitutes a true test of performance. IT DOESN'T.


Nov 8, 2006 at 9:38 PM // reply »
15 Comments

Tony,

given Ben's CFC's can you give specifics on how this should be tested instead?


Nov 8, 2006 at 11:27 PM // reply »
111 Comments

Hi Tony,

I agree that load testing will pick up on things that loop testing won't (especially as it relates to multiple thread and garbage collection and the like).

I don't think it is fair to talk about a process causing the disparity, though. That's why Ben ran the test multiple times.

FWIW, would love to see a post some time on best practices on (affordable) load testing for CF. Any postings you'd recommend or would you get a chance to do a quick posting yourself some time? I'd certainly love to learn how to do performance testing properly!


Nov 9, 2006 at 7:25 AM // reply »
11,238 Comments

Tony,

No worries on the tone; I am a fan of knowledge and truth. I would love to know how to test things in a more useful manner... I mean, that's why I do this type of stuff in the first place.

It makes me wonder though, what do you suppose the best use of the ColdFusion CFTimer tag would be? I pretty much only use it for testing in this fashion, but if this is not useful, I don't really see any use for the CFTimer tag. Any suggestions?


Nov 9, 2006 at 3:00 PM // reply »
7 Comments

Ben -

I've don't get good times from cftimer, so I use the standard way (end time - start time).


Nov 9, 2006 at 3:05 PM // reply »
11,238 Comments

Patrick,

But even regardless of the CFTimer tag and it's times... as Tony says, this type of testing isn't useful (CFTimer or end-start).

So my question is, if only true load testing is useful for performance testing, then what did the ColdFusion team have in mind when it created the CFTimer tag?


Mar 2, 2009 at 4:47 PM // reply »
149 Comments

Any updates on this? I'd love to hear Tony's suggestions.


Mar 2, 2009 at 6:08 PM // reply »
11,238 Comments

@David,

No updates recently. Sadly, over two years later and I'm still not making full use of ColdFusion components. I need to up this effort!


Feb 27, 2010 at 12:21 PM // reply »
113 Comments

@Ben,

It's absolutely true that you cannot get accurate benchmarks simply by running stuff in a loop like this. However, you can certainly get good comparative performance numbers. You can get a good sense of whether one technique is generally faster than another technique, at least for the particular workload under test.

In other words, you cannot use this to determine in advance how many servers you will need. But you can use this to determine which of two techniques will be significantly faster than the other.

An easy example: ColdFusion arrays are actually Java objects under the hood. They have Java methods. To find out the size of a ColdFusion array, you can use either <code>ArrayLen(array)</code> or <code>array.size()</code> and you can use either <code>array[i]</code> or <code>array.get(i - 1)</code> to get the element of the array at the given index (using the 1-based indices familiar to ColdFusion). But the version using <code>ArrayLen</code> and <code>[i]</code> will turn out to be much faster. And the simplest way to find this out is to use a loop to get comparative performance numbers.

By the way, I like to use <code>t = GetTickCount(); /* do something many times in a long loop...; */ t = GetTickCount() - t;</code> to get performance numbers rather than using <code>cftimer</code>, because I can store the numbers in one file (Application.cfc) and display them later in another file (admin/timers.cfm) or log them or whatever.

Cheers,
Justice


Feb 27, 2010 at 2:16 PM // reply »
11,238 Comments

@Justice,

I am surprised that using the ColdFusion methods is faster than using the direct Java methods. I would think you'd be side-stepping some additional method calls if you go directly to the Java layer.


Feb 27, 2010 at 2:31 PM // reply »
113 Comments

@Ben,

Surprise! :P It actually makes a lot of sense when you see what's going on under the hood.

When you use Java methods in ColdFusion, ColdFusion has to go and do a bunch of reflection to find the right method, convert the parameters to the native Java types, call the method, etc. Reflection is slow.

But when you use <code>ArrayLen</code>, ColdFusion can "turn on" some optimizations. It will check that the object is of the right type and then it calls the <code>size</code> method directly, internally within the <code>ArrayLen</code> function. There is no reflection involved, so that makes <code>ArrayLen</code> significantly faster.

Because ColdFusion is a dynamic language (dynamic in the sense that functions are looked up by name-and-signature resolution/reflection, rather than by a single-instruction function pointer dereference), method invocation is slow. Not terribly slow, because ColdFusion, the Java libraries, and the Java runtime all try to cache some things to speed up reflection, but noticeably slow.

Calls to the built-in ColdFusion functions, however, are not dynamically bound. They are statically bound. In other words, it's the same as a single-instruction function pointer lookup from statically-typed languages. That makes the built-in ColdFusion functions much faster, because invoking them does not rely on reflection.

Cheers,
Justice


Feb 27, 2010 at 2:35 PM // reply »
149 Comments

Assuming it's correct, that just blew my mind.


Feb 27, 2010 at 2:39 PM // reply »
11,238 Comments

@Justice, @David,

Right?!?! That is very fascinating. I really appreciate you clearing that up - I definitely thought just the opposite (not based on any evidence, just theory).


Feb 27, 2010 at 2:40 PM // reply »
149 Comments

Sidenote: Ben, just noticed your main page is /index.cfm and all of your entries and the member profiles rock a .htm extension.

What the what? Is that some kind of trick-people-and-computers-into-thinking-it's-1990-again caching or pyramid scheme technique you're using? What's going on? I'm guessing the htm files don't actually exist and that you're using url simulation like the majority of other sites in the world, but if so, why the .htm suffix? Very curious.


Feb 27, 2010 at 2:45 PM // reply »
11,238 Comments

@David,

The HTM files don't actually exist. I used to use 404-handling; now, I use URL rewriting with IIS-MOD-Rewrite. I chose the HTM file extension years ago before I had url rewriting skills and before ColdFusion has onMissingTemplate(). It was the only way I could "Catch" a missing page without ColdFusion invoking something internal.

Also, I was told a long time ago that htm files appear more "static" to Search Engines; but, that could just be old-school thinking.


Feb 27, 2010 at 2:53 PM // reply »
149 Comments

Ah gotcha, makes perfect sense.


Apr 27, 2010 at 10:12 PM // reply »
22 Comments

I find getTickCount() doesn't have enough granularity - it only deals with milliseconds.
I prefer to work with nanoseconds (1ms = 1,000,000ns)

Rather than executing something in a loop 1000x times with cftimer, I use the system class timer. I'm sure there are java overheads that get in the way, but gives a pretty good estimate. Average a few separate page executions for additional accuracy.

// a reference to the system class
sys = createObject('java','java.lang.System');

// get a 'tick count' in nanoseconds
ns = sys.nanoTime();

// do something eg.
sleep(1000);

// number of nanoseconds is the new 'tick' minus the old
ns = sys.nanoTime() - ns;


May 18, 2010 at 9:35 PM // reply »
11,238 Comments

@Mike,

Oh cool - I didn't know about that. I was not aware that we could get any values smaller than milliseconds.


May 21, 2010 at 10:44 AM // reply »
2 Comments

Hi Ben -- I just started getting into CFCs (yeah, I know, I'm about 8 years late to the party) and am really liking them, and would also like to take time here to offer a hearty thank-you to you for all the great advice and work you've done on your site.

My question -- in your example CFCs, I see you have the following:

<cfset VARIABLES.InstanceID = CreateUUID() />

In all the examples I've seen so far in the WACK book, it looks like we're supposed to use the var scope, i.e.:

<cfset var InstanceID = CreateUUID() />

Did you not care about this because this was only a test CFC? For best practice, unless you wanted to share the InstanceID variable to all methods in the object, you shouldn't do this, right? Of course, in your case here, I don't think this mattered at all.

- Sung


May 21, 2010 at 9:40 PM // reply »
11,238 Comments

@Sung,

Good question - the "var" keyword is only used within the confines of a CFFunction tag (it has not meaning elsewhere... with one exception). It's use is meant to define a variable in the "local" scope of a function. See, if you don't use it, and you set a variable inside of a function, the variable "leaks" into the variables scope of the component. So, if you had something like this:

<cffunction>
<cfset message = "hello" />
</cffunction>

... the variable "message" is actually getting stored into the variables scope of the component. This is essentially the same as this:

<cffunction>
<cfset variables.message = "hello" />
</cffunction>

In order to NOT alter the variables scope of the component, you use the VAR keyword to ensure that the variable is defined in the context of the CFFunction tag and NOT the greater CFComponent variables scope:

<cffunction>
<cfset var message = "hello" />
</cffunction>

Typically, variables that you define within a CFFunction are only meant to be used for the duration of the actual function. As such, you should use the "var" keyword to make sure you don't accidentally alter the component long-term. That is not to say that you always need to do that. If you want to alter the variables scope, you certainly can. The trick is just to know the difference.

I hope that helps a bit??


May 26, 2010 at 9:58 PM // reply »
2 Comments

Dear Ben,

Thanks, man -- yeah, it helps a lot! So have you still not gotten into using the "extends" property? I don't really get the attraction for it. I mean you can just CreateObject() whatever components you want inside a component, so what does the extends property really get you?

- Sung


Jun 7, 2010 at 10:54 PM // reply »
11,238 Comments

@Sung,

I use the Extends property when I need to create base functionality. My domain models haven't gotten too complex yet (still not whole-hog into OOP just yet). So for me, base functionality tends to revolve around implicit setter/getter methods via onMissingMethod() functionality. Other than that, I don't use it all that much.


Aug 10, 2010 at 2:52 PM // reply »
158 Comments

@Sung, (and maybe @Ben)

My co-worker and I have had troubles overwriting each other's work. We've got CFCs like "Functions.cfc" If I update it, I might overwrite some of his work, and vice versa.

Anyway, I'm hoping this could be a way we could break out our functions into "func1.cfc" and "Func2.cfc," "add_two_plus_two.cfc" etc... That way, when 2+2 suddenly equals five, I can update "add_two_plus_two.cfc" to reflect the new laws of physics.

Before I do this, though, I was hoping Sung might be able to confirm this is workable.


Aug 10, 2010 at 3:04 PM // reply »
113 Comments

@Randall

Use a version control system such as Subversion, Git, Mercurial, or Darcs (or others). That is the solution to your problem. Your suggestion will simply make your existing problem even worse.

Cheers,
Jay


Aug 10, 2010 at 3:38 PM // reply »
158 Comments

@Justice, I agree, but there's some hurdles to that -- money and red tape. Even if we did have CVS, the one I investigated was command line (the free version anyway). That's a hassle. I want to hit the save button and pop up a window, mostly pre-filled. Not only that, if he overwrites my work, we'd still have to figure out what was / wasn't changed. So I think I'd still want to do this even if we had a VCS like CVS, etc. It'd simplify tracking down the functions that don't work and replacing that one function (CFC file) with an older/stable version.


Aug 10, 2010 at 9:40 PM // reply »
11,238 Comments

@Randall,

Hmm, I am tending to agree with @Justice here. Is there any way that you can possibly just not work on the same components at the same time? Are there certain functions that one of you always works on?


Aug 11, 2010 at 11:09 AM // reply »
158 Comments

@Ben,

Absolutely, but that doesn't solve the problem. I'll work on CFC1-Funct1 and he'll work on CFC1-Funct3 at different times. If we have multiple release versions open -- say, "v3.3" and "v3.4" with production being v3.2, we have to make changes to 3.3 and replicate them to 3.4. But, if he changed v3.4-CFC1-Funct3 and I changed v3.3-CFC1-Funct1 and overwrite v3.4-CFC1.cfc, then his changes may get overwritten.

Now, I'm sure you're asking, "Why do you have mult versions open?" Just.... don't ask; It's the management. ;-) Again, we know a VCS would be the solution and being more cautious, but if we get in a hurry -- or don't think anything else changed -- mistakes happen.

We'll give this a shot on a handful of functions and see what happens.


Aug 14, 2010 at 12:50 PM // reply »
11,238 Comments

@Randall,

I am mostly saying this as a *joke* (not as advice), but if you have certain functions that YOU always work on and certain functions that someone else always works on, then you could always split the CFC and have one extend the other:

ActualCFC.cfc (extends >>)
RandallCFC.cfc (extends >>)
OtherPersonCFC.cfc

... then each of you could safely work on a sub-set of CFC methods.

Again, I am not really serious about this suggestion... but it would work.


Sep 7, 2010 at 8:45 PM // reply »
1 Comments

@Ben & @Mike,

A couple of things to keep in mind with Java in general with regards to time:

1. Java's standard timers have different accuracies on different OSes. For example, on Windows, most of the timers are only accurate to 15-16ms. Linux is generally accurate to 1 ms. This means that test accuracy relying on clocks are most likely only going to be accurate within this same window.

2. Java's "nanotime" calculations are only useful relative to one another. Also, within that, you have to be careful because the nanotime returns a long which rolls over relatively often, so over a long test run, you need to do tests of the nanotime values being compared to ensure that a roll over didn't occur. If a roll over does occur, the subtraction method will throw your test results / timing way off.

I'm not 100% sure how heavily ColdFusion uses Java's timing, but those are a couple of gotchas that I have seen hurt Java programmers pretty regularly when trying to deal with tight timings.


Sep 10, 2010 at 9:02 PM // reply »
11,238 Comments

@Steven,

Good point with the timer accuracy. Othe people have also pointed out that there is only so much that you can actually glean from this type of performance testing (testing withOUT load). At least I'm not seeing any red flags with this approach, which has to be a good sign even without the accuracy.


Jan 19, 2011 at 2:28 PM // reply »
158 Comments

I just discovered that our system has a WHOLE LOT of

  • <cfobject type="component" name="something" component="comp">
  • <cfobject type="component" name="something" component="comp">
  • <cfobject type="component" name="something" component="comp">

In other words, the same thing is repeated seemingly unnecessarily.

Does this cause a performance hiccup? Extra memory usage?

Anyone?


Jan 19, 2011 at 2:32 PM // reply »
149 Comments

Yes, it runs each line like any other code so unless the underlying code checks for some state change it'll cost you the full server resources of running it x ( 3 ) times.

It looks like you had a super OCD programmer to be honest. Get him some pills or something hahahahah.


Jan 20, 2011 at 10:02 AM // reply »
158 Comments

Slightly new topic - I have three CFCs:

C extends B
B extends A
A is the head honcho.

Can A reference functions in B & C if they're private?

I did some tests yesterday and I think the answer is *NO*, but had trouble finding the answer on the series of tubes, and wondered if I was doing something incorrectly.

To me, it seems like a component (A) with extension functions (B.cfc & C.cfc) should be able to use the functions inside B & C since they're children.

Or should I think of this in reverse? Thus write my functions in C, then refer to the "super" functions of B and A?


Jan 20, 2011 at 10:48 AM // reply »
149 Comments

Sadly, no.

Inheritance is one way, downstream.

C inherits all of B and A's functions, B all of A's, but A was basically a sperm donor, dropping his genes and disappearing. A can never use any of the functions from any of its children or grandchildren via inheritance.

Any common functionality that you want to use across all 3 needs to be moved further upstream to A.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools