• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Function calling from components

Explorer ,
Jun 21, 2021 Jun 21, 2021

Copy link to clipboard

Copied

Hello,

 

Just a query on 2 differing ways of calling a function from a component in Coldfusion. I've always called functions in one of 2 ways. 

 

Method 1:

 

 

<cfset myComponent = createObject("component", "pathToMyComponent.componentGet")>
 
<cfset myVariable= myComponent.getKey (
                                                                    data = someDSN,
                                                                    key = myKey,
                                                                    ........)>​

 

Method 2:
 

 

<cfinvoke component="pathToMyComponent.componentGet" method="getKey "  returnvariable="myVariable">
                    <cfinvokeargument name="data" value="#someDSN#">
                    <cfinvokeargument name="key" value="#myKey#">
                    .......
          </cfinvoke>

 

 

My question would be is there any overhead using Method 1 over Method 2. I assume there must be as you are instantiating an entire component, then only using 1 function. Method 2 would be my preferred way of calling a function but we would still have lots of calls made using Method 1. Just wondering what the advantages of one over the other would be and whats best from system memory/performance point of view?

 

Thanks

Views

274

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jun 21, 2021 Jun 21, 2021

Paul, that's a classic question. And if ALL you do in your code is those two examples, then there is technically NO difference or advantage of one over the other. Both of them "are instantiating an entire component, then only using 1 function."

 

But sure, if you really meant to say that you would go on and call many more methods in that CFC (or all that one over and over) in a given request, then yes there's for sure an advantage to saving the instantiation in a variable and calling the methods

...

Votes

Translate

Translate
Community Expert ,
Jun 21, 2021 Jun 21, 2021

Copy link to clipboard

Copied

Paul, that's a classic question. And if ALL you do in your code is those two examples, then there is technically NO difference or advantage of one over the other. Both of them "are instantiating an entire component, then only using 1 function."

 

But sure, if you really meant to say that you would go on and call many more methods in that CFC (or all that one over and over) in a given request, then yes there's for sure an advantage to saving the instantiation in a variable and calling the methods using that.

 

FWIW, you can do that sort of thing not only with createobject but also <cfobject>, as well as the "new" keyword that was added in CF9 (and while many resources make a point about how using that new keyword will call an init method, you don't NEED to have one to use it).

 

And for the sake of completness, one can even use cfinvoke (or its script equivalent, invoke) to invoke methods on a CFC that was instantiated and saved using cfobject or createobject. But the way you're doing things is fine and indeed preferable to most.

 

If it's of any value, this topic is discussed in considerably more detail in the CF docs (not the CFML Reference) in the Developer's Guide chapter on using CFCs.


/Charlie (troubleshooter, carehart.org)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 21, 2021 Jun 21, 2021

Copy link to clipboard

Copied

Thanks Charlie.

 

quote

But sure, if you really meant to say that you would go on and call many more methods in that CFC (or all that one over and over) in a given request, then yes there's for sure an advantage to saving the instantiation in a variable and calling the methods using that.

 

I'll certainly take the above on board as I would have mulitple areas where I would call the same function within a loop so method 1 would seem best utilised in this scenario. I wouldnt have considered that previously and would have just called the function whatever way was closest to hand at that time. I had also had a little google to find the answer but hadn't come across that article you included. Would have saved myself a post.

 

Paul

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 21, 2021 Jun 21, 2021

Copy link to clipboard

Copied

Glad to have helped.

 

And yes, sadly, when people google things related to CF they don't tend to be shown that Developer's Guide, which is a real shame. They tend to only be taken to the CFML Reference, which is like learning to speak english from a dictionary. The Dev Guide is about 3,000 pages if printed and has lots of great info.

 

And tragically, the Adobe doc engine doesn't handle its considerable depth (of chapters, subchapters, sections) well, so sometimes you hit what seem deadends in the UI.

 

But using google search keywords to search for things in that specific guide can help find them, like:

 

site:helpx.adobe.com inurl:coldfusion/developing-applications cfcs

 

which finds that very URL as the first result. 🙂 I'm not saying that to suggest you should have tried it (which is what many mean when they say to google something), but really just to show how this technique should help a lot, for you and others who may find this. 🙂


/Charlie (troubleshooter, carehart.org)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 22, 2021 Jun 22, 2021

Copy link to clipboard

Copied

@paulm1677332 , you can actually answer the question yourself. 🙂

Here's how you can easily compare the performance of the two methods:

 

1) Go to the ColdFusion Administrator's Server Settings > Caching page. Uncheck the checkbox Save class files. That will ensure that, in the test we are about to do, classes won't be saved and reused. That way, we shall be comparing like with like.

2) The test code consists of a CFC (Benchmark.cfc) and a CFM (compareIt.cfm). Place them in the same directory under the web root. I have chosen names for variables that make the code self-explanatory and self-documenting. 

3) Run compareIt.cfm.

 

 

<!--- Benchmark.cfc --->
<cfcomponent>
	<cffunction name="getKey" returntype="string" output="false">
		<cfargument name="data" type="string">
		<cfargument name="key" type="string">
		
		<cfset var theKey = arguments.data & "_" & arguments.key>
		
		<cfreturn theKey>		
	</cffunction>
</cfcomponent>

<!--- compareIt.cfm --->
<!--- Page set to time out after 120 seconds. Just to prevent it taking forever.--->
<cfsetting RequestTimeout = "120">

<!--- Test in turn with 10000, 20000, 30000, 50000, 80000, 150000 --->
<cfset loopCount = 5000>

<cfset someDSN = "someDSN">
<cfset myKey = createUUID()>

<cfset method_1_startTimer = getTickCount()>

<cfloop from="1" to="#loopCount#" index="i">
	<cfset myComponent = createObject("component", "Benchmark")>
	<cfset myVariable= myComponent.getKey(data = someDSN, key = myKey)>
</cfloop>
​
<cfset method_1_executionTime = getTickCount() - method_1_startTimer> 

<p>
<cfoutput>	
	Method 1 result: #myVariable# <br>
	Method 1 execution time for #loopCount# loops: #method_1_executionTime# ms<br>	 
</cfoutput>
</p>

<cfset method_2_startTimer = getTickCount()>

<cfloop from="1" to="#loopCount#" index="j">
	<cfinvoke component="Benchmark" method="getKey"  returnvariable="myVariable">
		<cfinvokeargument name="data" value="#someDSN#">
		<cfinvokeargument name="key" value="#myKey#">
	</cfinvoke>
</cfloop>

<cfset method_2_executionTime = getTickCount() - method_2_startTimer>

<p>
<cfoutput>	
	Method 2 result: #myVariable# <br>
	Method 2 execution time for #loopCount# loops: #method_2_executionTime# ms<br>	 
</cfoutput>
</p>   

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 22, 2021 Jun 22, 2021

Copy link to clipboard

Copied

LATEST

Thanks, BKBK. Some may wish you would have reported what results you got, so they would not have to run it themselves to see. 🙂 Of course, I appreciate that there's value in each running any such tests on their own, as different things can influence their results.

 

FWIW, I will share that I found that the method 2 approach was about 10% slower on average than method 1, and that was in tests against CF2021, 2018, and 2016, running their latest versions.

 

And if anyone is interested, you can run that code also for yourself without having CF installed, via Adobe's cffiddle.org site. If you login, you can run my implementation of BKBK's code here. But again, note that you MUST login there (via google or facebook) to see such "apps". (Anyone can run simple single template requests there even without a login.) And in case it hits anyone else, I will say that my attempt to login via facebook there fails (and has in recent days), but my logging in via google works fint.

 

That said, I would offer this warning about such micro benchmarks (running thousands of executions in a loop), as sometimes the JVM will optimize things within a given request (especially a tight loop) so that they perform quote differently than if instead you had setup a load test to call pages doing things the one way or the other. Just food for thought.

 

Finally, I really doubt you'd see any difference at all if you did or did no thave "Save class files" enabled. That should only have an impact on the first execution of the CFC after a CF restart, which will CF load from that saved classes location if it exists there. (Of course, we have no control of that when running at the cffiddle.org site.) If you may have demonstrated a difference in your results based on that, again, it would be interesting to hear.

 

As always, just trying to help, as I know you always are also BKBK.


/Charlie (troubleshooter, carehart.org)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation