I have a legacy app that I’m finally bringing into the 21st Century. It uses a bunch of UDFs, mostly from cflib.org. Nevermind for now that I need to pick through all those and either update them or replace with more modern solutions. I’m well aware.
The point of this topic is that one of the things I assumed I needed to do for maximum performance is to move all those UDFs into the Application scope so they’re only loaded once into memory onApplicationStart() instead of with every Request, but as has been discussed before, for some reason that appears to introduce a performance decrease.
What hasn’t been shared before is a comparison of simple timers which indicate the slightly longer run times when UDFs are called from the Application scope. My first thought was that it must be because I was testing with just a very simple function, but I got the same results after beefing up both udf.cfm and udf.cfc (see below) with more than 2400 lines of code from the cflib functions.
Is there something incorrect about my test code? Is there caching of my udf.cfm that is just as good as Application scope caching? Or is it simply because all .cf* files are compiled into Java binaries?
It’s not much of a difference, but I’m curious to know the reason why. And the whole point was to improve performance, so if that’s not happening then should I even bother moving the UDFs into Application scope?
Application.cfm
component {
function onApplicationStart() {
// Instantiate User Defined Functions (UDF) as Singletons so they're cached for the entire Application
Application.udf = new udf();
}
}
udf.cfm
<cfscript>
function hello() {
echo('hello from included udf.cfm!');
}
</cfscript>
udf.cfc
component {
function hello() {
echo('hello from Application.udf!');
}
}
timer-udf-app.cfm
<cfscript>
Application.udf.hello();
</cfscript>
timer-udf-include.cfm
<cfscript>
include "udf.cfm";
hello();
</cfscript>
timer-udf-include-vs-app.cfm
<cfscript>
// cfhttp() is used to simulate multiple Requests
echo('udf via app');
timer type="outline" {
loop times=1000 {
cfhttp(method="get" url="http://localhost/timer-udf-app.cfm");
}
}
echo('udf via include');
timer type="outline" {
loop times=1000 {
cfhttp(method="get" url="http://localhost/timer-udf-include.cfm");
}
}
/*
Test Results With Simple UDFs:
udf via app 2651ms
udf via include 2515ms
Test Results When Using Large UDFs:
udf via app 2792ms
udf via include 2624ms
*/
</cfscript>
OS: Pop!_OS (Ubuntu fork) 21.10
Java Version: 11.0.6
Tomcat Version: 9.0.31
Lucee Version: 5.3.9.141