We noticed a severe performance issue in a part of our code when running on Lucee 6.2.1.122 in a test instance; this seems to have been introduced as far back as some time between 5.4.4.38 (running fine) and 5.4.5.23 (first affected version). I have created test code to illustrate the issue:
2025-05-27_LuceeReplaceNoCase.zip (64.1 KB)
<cfscript>
/*
start cfengine=lucee@5.4.4.38
start cfengine=lucee@5.4.5.23
*/
echo("Lucee Version: #server.lucee.version#<br />");
i=0;
cftimer(label=i++, type="inline"){
myText = fileRead("./example.txt");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, chr(9), "", "ALL");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, chr(10), "", "ALL");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, chr(13), "", "ALL");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, "[IMAGEGALLERY]", "", "ALL");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, "[INDEX]", "", "ALL");
}
echo('<br />');
cftimer(label=i++, type="inline"){
myText = ReplaceNoCase(myText, "[br]", "<br>", "ALL");
}
echo('<br />');
</cfscript>
We usually run on Debian 12, Tomcat 9 and Java 11, but I can reproduce the issue using commandbox on my home desktop computer running Windows 11, Java 11 and undertow on AMD Ryzen 7 5700X3D with 16GB RAM.
Here are the timings:
Lucee Version: 5.4.4.38
box start cfengine=lucee@5.4.4.38
0: 1ms
1: 1ms
2: 50ms
3: 11ms
4: 2ms
5: 0ms
6: 38ms
Lucee Version: 5.4.5.23
box start cfengine=lucee@5.4.5.23
0: 0ms
1: 2ms
2: 1384ms
3: 381ms
4: 1ms
5: 0ms
6: 1129ms
Lucee Version: 6.2.1.122
box start cfengine=lucee@6.2.1.122
0: 1ms
1: 2ms
2: 1403ms
3: 391ms
4: 0ms
5: 1ms
6: 1137ms
In extreme cases on our production machines, this means a total execution time of about 200ms for 5.4.4.38 increasing to 30 or 40 seconds when running on Lucee >=5.4.5.23 or Lucee 6.2.1.122, the latter already running on tomcat 10 and OpenJDK Runtime Environment Temurin-21.0.6+7, so it’s not an issue of the Java or servlet container version.
I know that I wouldn’t actually need to use replaceNoCase for specific chars, but this is part of a dynamic replacement mechanism, I just tried to boil this down to a clear test case.
So something was introduced after 5.4.4.38 and in or before 5.4.5.23 that severely affects the performance of replaceNoCase.
If it helps at all, here’s an excerpt from the FusionReactor profiler for this issue (running Lucee 5.4.7.3 here, which is also affected):
100.0% - 59.981s lucee.runtime.functions.string.ReplaceNoCase.call(ReplaceNoCase.java)
100.0% - 59.981s lucee.runtime.functions.string.ReplaceNoCase._call(ReplaceNoCase.java)
100.0% - 59.981s lucee.runtime.functions.string.ReplaceNoCase._call(ReplaceNoCase.java)
100.0% - 59.981s lucee.commons.lang.StringUtil.replace(StringUtil.java)
100.0% - 59.981s lucee.commons.lang.StringUtil._replace(StringUtil.java)
100.0% - 59.981s lucee.commons.lang.StringUtil.indexOfIgnoreCase(StringUtil.java)
93.5% - 56.074s java.lang.String.toUpperCase(String.java)
93.5% - 56.074s java.lang.String.toUpperCase(String.java) (hide)
93.5% - 56.074s java.lang.StringUTF16.toUpperCase(StringUTF16.java)
93.5% - 56.074s java.lang.StringUTF16.toUpperCaseEx(StringUTF16.java)
59.7% - 35.815s java.lang.StringUTF16.newBytesFor(StringUTF16.java)
59.7% - 35.815s Self Time
33.4% - 20.034s Self Time
0.4% - 225ms java.lang.StringUTF16.newString(StringUTF16.java)
0.4% - 225ms java.lang.StringUTF16.compress(StringUTF16.java)
0.4% - 225ms Self Time
Shall I file a new bug for this?