Tip: String functions in Lucee are extremely slow

Our site is old… I mean even by Internet standards, our site is old. We’re celebrating our 20th birthday this year. And we’ve been running our site on CFML all these years. And yes, there’s still tons of old code in use, that has been patched, hacked, tweaked and superglued over these years.

And we’ve tried pretty much all the CFML engines. I think we started with Adobe (or was it still Altaire when we started… or Macromedia already… cannot remember) ColdFusion back in a day. At some stage we then switched to Blue Dragon… Once that died, we jumped to OpenBD. And most recently, about a year ago, we switched to Lucee.

Each and every server platform has had its own bugs and problems over these years. And for each and every platform we’ve had to make various hacks to the code to avoid the problems.

Ok…

One of those hacks has been our own date output function, to replace DateTimeFormat(), called in our systems niceDate()… It does exactly the same what CFML’s own function does, but as when we had to write it, the locale support of the then server we had in use (cannot remember which one) had a very poor number of locales supported. Thus, to have those nice “long” strings like “Monday” or “December” to output in languages we needed (Finnish, to be precise, back then) we had to do our own parser.

It was just a simple bunch of replaces, Left()s and Right()s and whatnot and it allowed to pass a locale argument in to it, but obviously as it was hardcoded, it only supported those locales we had hardcoded into it. But it suited our purpose all these years. So, for every timestamp and date string we outputted, that function was used. niceDate(now(), “d mmm, yyyy”, “fi”) or whatever.

We switched to Lucee a year ago and while most pages were actually executed faster than on our previous OpenBD platform (sure, also the servers got more oomph as we switched also to new boxes). But some important pages threw timeouts pretty often to the error logs.

As we’ve been very busy over the past year with various business issues and some new code development, we didn’t think too much about this. But yesterday, when we were going through one of those “problem pages” due totally different reason, we finally took time to debug the issue.

And yep… The niceDate() function we had buitl that did about 20 - 80 Replaces (no regex) slowed down the page dramatically.

Finding all the places where the function was used and replacing it finally with LSDateTimeFormat() took several hours (as it involved also checking the other code on those dusty old pages, too).

But ta-daa… After the change we haven’t had a single timeout recorded to the error logs. None. And we did get about 800 of those a day (out of appx two hundred thousand requests a day).

So, problem solved, but kinda tip for the people who might be wondering about their code speed - and for developers of Lucee to look into.

And no, we aren’t running the latest Lucee, so I apologize if this has been fixed in later versions. We simply cannot take the time too often to update all of our servers and to test that new version works on all templates as it should. We’re running currently the 5.2.6.60 on our production servers.

Just my €0.02…

Can you file a bug with some examples?

Alright, I did add an issue to JIRA.

1 Like

thank you!

https://luceeserver.atlassian.net/browse/LDEV-2188

<cffunction name="niceDate" returnType="string" output="no">
	<cfargument name="pvm" type="date">
	<cfargument name="maski" type="string">
	<cfargument name="lang" type="string" default="en">

	<cfif Find("mmm",maski) gt 0 and Find("mmmm",maski) eq 0>
		<cfset kolme="true">
	</cfif>

	<cfset maski=Replace(maski, "dddd", UCase(DayOfWeekAsString(DayOfWeek(pvm))), "ALL")>
	<cfset maski=Replace(maski, "ddd", UCase(Left(DayOfWeekAsString(DayOfWeek(pvm)), 3)), "ALL")>

	<cfif Day(pvm) lt 10>
		<cfset maski=Replace(maski, "dd", "0"&Day(pvm), "ALL")>
	<cfelse>
		<cfset maski=Replace(maski, "dd", Day(pvm), "ALL")>
	</cfif>
	<cfset maski=Replace(maski, "d", Day(pvm), "ALL")>


	<cfset maski=Replace(maski, "mmmm", UCase(MonthAsString(Month(pvm))), "ALL")>
	<cfset maski=Replace(maski, "mmm", UCase(Left(MonthAsString(Month(pvm)), 3)), "ALL")>

	<cfif Month(pvm) lt 10>
		<cfset maski=Replace(maski, "mm", "0"&Month(pvm), "ALL")>
	<cfelse>
		<cfset maski=Replace(maski, "mm", Month(pvm), "ALL")>
	</cfif>

	<cfset maski=Replace(maski, "m", Month(pvm), "ALL")>
	<cfset maski=Replace(maski, "yyyy", Year(pvm), "ALL")>

	<cfif Hour(pvm) lt 10>
		<cfset maski=ReplaceNoCase(maski, "hh", "0"&Hour(pvm), "ALL")>
	<cfelse>
		<cfset maski=ReplaceNoCase(maski, "hh", Hour(pvm), "ALL")>
	</cfif>

	<cfset maski=ReplaceNoCase(maski, "h", Hour(pvm), "ALL")>
	<cfif Minute(pvm) lt 10>
		<cfset maski=ReplaceNoCase(maski, "nn", "0"&Minute(pvm), "ALL")>
	<cfelse>
		<cfset maski=ReplaceNoCase(maski, "nn", Minute(pvm), "ALL")>
	</cfif>
	<cfset maski=Replace(maski, "n", Minute(pvm), "ALL")>

	<cfset maski=Replace(maski, "ss", Second(pvm), "ALL") />

	<cfloop from="1" to="7" index="paiva">
		<cfset maski=Replace(maski, UCase(DayOfWeekAsString(paiva)), DayOfWeekAsString(paiva), "ALL")>
		<cfset maski=Replace(maski, Left(UCase(DayOfWeekAsString(paiva)), 3), Left(DayOfWeekAsString(paiva), 3), "ALL")>
	</cfloop>

	<cfloop from="1" to="12" index="kuukausi">
		<cfset maski=Replace(maski, UCase(MonthAsString(kuukausi)), MonthAsString(kuukausi), "ALL")>
		<cfset maski=Replace(maski, Left(UCase(MonthAsString(kuukausi)), 3), Left(MonthAsString(kuukausi), 3), "ALL")>
	</cfloop>

	<cfif lang is "fi">

		<cfset maski=Replace(maski, "January", "tammikuuta", "ALL")>
		<cfset maski=Replace(maski, "February", "helmikuuta", "ALL")>
		<cfset maski=Replace(maski, "March", "maaliskuuta", "ALL")>
		<cfset maski=Replace(maski, "April", "huhtikuuta", "ALL")>
		<cfif isdefined("kolme")>
				<cfset maski=Replace(maski, "May", "tou", "ALL")>
		<cfelse>
				<cfset maski=Replace(maski, "May", "toukokuuta", "ALL")>
		</cfif>
		<cfset maski=Replace(maski, "June", "kes&auml;kuuta", "ALL")>
		<cfset maski=Replace(maski, "July", "hein&auml;kuuta", "ALL")>
		<cfset maski=Replace(maski, "August", "elokuuta", "ALL")>
		<cfset maski=Replace(maski, "September", "syyskuuta", "ALL")>
		<cfset maski=Replace(maski, "October", "lokakuuta", "ALL")>
		<cfset maski=Replace(maski, "November", "marraskuuta", "ALL")>
		<cfset maski=Replace(maski, "December", "joulukuuta", "ALL")>
		<cfset maski=Replace(maski, "Jan", "tam", "ALL")>
		<cfset maski=Replace(maski, "Feb", "hel", "ALL")>
		<cfset maski=Replace(maski, "Mar", "maa", "ALL")>
		<cfset maski=Replace(maski, "Apr", "huh", "ALL")>
		<cfset maski=Replace(maski, "Jun", "kes", "ALL")>
		<cfset maski=Replace(maski, "Jul", "hei", "ALL")>
		<cfset maski=Replace(maski, "Aug", "elo", "ALL")>
		<cfset maski=Replace(maski, "Sep", "syy", "ALL")>
		<cfset maski=Replace(maski, "Oct", "lok", "ALL")>
		<cfset maski=Replace(maski, "Nov", "mar", "ALL")>
		<cfset maski=Replace(maski, "Dec", "jou", "ALL")>
		<cfset maski=Replace(maski, "Monday", "maanantai", "ALL")>
		<cfset maski=Replace(maski, "Tuesday", "tiistai", "ALL")>
		<cfset maski=Replace(maski, "Wednesday", "keskiviikko", "ALL")>
		<cfset maski=Replace(maski, "Thursday", "torstai", "ALL")>
		<cfset maski=Replace(maski, "Friday", "perjantai", "ALL")>
		<cfset maski=Replace(maski, "Saturday", "lauantai", "ALL")>
		<cfset maski=Replace(maski, "Sunday", "sunnuntai", "ALL")>
		<cfset maski=Replace(maski, "Mon", "ma", "ALL")>
		<cfset maski=Replace(maski, "Tue", "ti", "ALL")>
		<cfset maski=Replace(maski, "Wed", "ke", "ALL")>
		<cfset maski=Replace(maski, "Thu", "to", "ALL")>
		<cfset maski=Replace(maski, "Fri", "pe", "ALL")>
		<cfset maski=Replace(maski, "Sat", "sa", "ALL")>
		<cfset maski=Replace(maski, "Sun", "su", "ALL")>
	<cfelseif lang is "sv" or lang is "swe">
		<cfset maski=Replace(maski, "January", "januari", "ALL")>
		<cfset maski=Replace(maski, "February", "februari", "ALL")>
		<cfset maski=Replace(maski, "March", "mars", "ALL")>
		<cfset maski=Replace(maski, "April", "april", "ALL")>
		<cfif isdefined("kolme")>
			<cfset maski=Replace(maski, "May", "maj", "ALL")>
		<cfelse>
			<cfset maski=Replace(maski, "May", "maj", "ALL")>
		</cfif>
		<cfset maski=Replace(maski, "June", "juni", "ALL")>
		<cfset maski=Replace(maski, "July", "juli", "ALL")>
		<cfset maski=Replace(maski, "August", "augusti", "ALL")>
		<cfset maski=Replace(maski, "September", "september", "ALL")>
		<cfset maski=Replace(maski, "October", "oktober", "ALL")>
		<cfset maski=Replace(maski, "November", "november", "ALL")>
		<cfset maski=Replace(maski, "December", "december", "ALL")>
		<cfset maski=Replace(maski, "Jan", "jan", "ALL")>
		<cfset maski=Replace(maski, "Feb", "feb", "ALL")>
		<cfset maski=Replace(maski, "Mar", "mar", "ALL")>
		<cfset maski=Replace(maski, "Apr", "apr", "ALL")>
		<cfset maski=Replace(maski, "Jun", "jun", "ALL")>
		<cfset maski=Replace(maski, "Jul", "jul", "ALL")>
		<cfset maski=Replace(maski, "Aug", "aug", "ALL")>
		<cfset maski=Replace(maski, "Sep", "sep", "ALL")>
		<cfset maski=Replace(maski, "Oct", "okt", "ALL")>
		<cfset maski=Replace(maski, "Nov", "nov", "ALL")>
		<cfset maski=Replace(maski, "Dec", "dec", "ALL")>
		<cfset maski=Replace(maski, "Monday", "måndag", "ALL")>
		<cfset maski=Replace(maski, "Tuesday", "tisdag", "ALL")>
		<cfset maski=Replace(maski, "Wednesday", "onsdag", "ALL")>
		<cfset maski=Replace(maski, "Thursday", "torsdag", "ALL")>
		<cfset maski=Replace(maski, "Friday", "fredag", "ALL")>
		<cfset maski=Replace(maski, "Saturday", "lördag", "ALL")>
		<cfset maski=Replace(maski, "Sunday", "söndag", "ALL")>
		<cfset maski=Replace(maski, "Mon", "må", "ALL")>
		<cfset maski=Replace(maski, "Tue", "ti", "ALL")>
		<cfset maski=Replace(maski, "Wed", "on", "ALL")>
		<cfset maski=Replace(maski, "Thu", "to", "ALL")>
		<cfset maski=Replace(maski, "Fri", "fr", "ALL")>
		<cfset maski=Replace(maski, "Sat", "lö", "ALL")>
		<cfset maski=Replace(maski, "Sun", "sö", "ALL")>
	<cfelseif lang neq "en" and lang neq "eng" and isdefined("translations.general.dateStuff.listOfMonths")>
		<cfset maski=Replace(maski, "January", ListGetAt(translations.general.dateStuff.listOfMonths, 1), "ALL")>
		<cfset maski=Replace(maski, "February", ListGetAt(translations.general.dateStuff.listOfMonths, 2), "ALL")>
		<cfset maski=Replace(maski, "March", ListGetAt(translations.general.dateStuff.listOfMonths, 3), "ALL")>
		<cfset maski=Replace(maski, "April", ListGetAt(translations.general.dateStuff.listOfMonths, 4), "ALL")>
		<cfif isdefined("kolme")>
			<cfset maski=Replace(maski, "May", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 5)), 3), "ALL")>
		<cfelse>
			<cfset maski=Replace(maski, "May", ListGetAt(translations.general.dateStuff.listOfMonths, 5), "ALL")>
		</cfif>
		<cfset maski=Replace(maski, "June", ListGetAt(translations.general.dateStuff.listOfMonths, 6), "ALL")>
		<cfset maski=Replace(maski, "July", ListGetAt(translations.general.dateStuff.listOfMonths, 7), "ALL")>
		<cfset maski=Replace(maski, "August", ListGetAt(translations.general.dateStuff.listOfMonths, 8), "ALL")>
		<cfset maski=Replace(maski, "September", ListGetAt(translations.general.dateStuff.listOfMonths, 9), "ALL")>
		<cfset maski=Replace(maski, "October", ListGetAt(translations.general.dateStuff.listOfMonths, 10), "ALL")>
		<cfset maski=Replace(maski, "November", ListGetAt(translations.general.dateStuff.listOfMonths, 11), "ALL")>
		<cfset maski=Replace(maski, "December", ListGetAt(translations.general.dateStuff.listOfMonths, 12), "ALL")>
		<cfset maski=Replace(maski, "Jan", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 1)), 3), "ALL")>
		<cfset maski=Replace(maski, "Feb", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 2)), 3), "ALL")>
		<cfset maski=Replace(maski, "Mar", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 3)), 3), "ALL")>
		<cfset maski=Replace(maski, "Apr", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 4)), 3), "ALL")>
		<cfset maski=Replace(maski, "Jun", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 6)), 3), "ALL")>
		<cfset maski=Replace(maski, "Jul", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 7)), 3), "ALL")>
		<cfset maski=Replace(maski, "Aug", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 8)), 3), "ALL")>
		<cfset maski=Replace(maski, "Sep", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 9)), 3), "ALL")>
		<cfset maski=Replace(maski, "Oct", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 10)), 3), "ALL")>
		<cfset maski=Replace(maski, "Nov", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 11)), 3), "ALL")>
		<cfset maski=Replace(maski, "Dec", Left(Trim(ListGetAt(translations.general.dateStuff.listOfMonths, 12)), 3), "ALL")>
		<cfset maski=Replace(maski, "Monday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 2), "ALL")>
		<cfset maski=Replace(maski, "Tuesday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 3), "ALL")>
		<cfset maski=Replace(maski, "Wednesday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 4), "ALL")>
		<cfset maski=Replace(maski, "Thursday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 5), "ALL")>
		<cfset maski=Replace(maski, "Friday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 6), "ALL")>
		<cfset maski=Replace(maski, "Saturday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 7), "ALL")>
		<cfset maski=Replace(maski, "Sunday", ListGetAt(translations.general.dateStuff.listOfWeekdays, 1), "ALL")>
		<cfset maski=Replace(maski, "Mon", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 1)), 2), "ALL")>
		<cfset maski=Replace(maski, "Tue", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 2)), 2), "ALL")>
		<cfset maski=Replace(maski, "Wed", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 3)), 2), "ALL")>
		<cfset maski=Replace(maski, "Thu", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 4)), 2), "ALL")>
		<cfset maski=Replace(maski, "Fri", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 5)), 2), "ALL")>
		<cfset maski=Replace(maski, "Sat", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 6)), 2), "ALL")>
		<cfset maski=Replace(maski, "Sun", Left(Trim(ListGetAt(translations.general.dateStuff.listOfWeekdays, 7)), 2), "ALL")>
	</cfif>
	<cfreturn maski>
</cffunction>

Here’s the entire ancient code. I know it is goddamn unsophisticated and in many ways hideous piece of code, but hey, it worked for us for more than a decade :smiley:

So, yeah, I assume running that once wont do much difference. But we had templates where the same function is/was used, say, for 200 times (listing software downloads older versions, for example, and when each version was originally updated) it seemed to slow down the processing ridiculously with Lucee.

And yeah, there might be some obvious gotchas there in the code that could’ve been improved by better testing/ thinking it properly. But as the function is not needed anymore, as LSDateTimeFormat() now works as it should, we aren’t too interested to think about it.

The €0.02 here is that many of us might have ancient code in various places and you kinda expect them to run at least on par with other CFML engines, not slower :slight_smile:

I think the main problem is all the ListGetAt, if you converted each translation to an array once, I’m sure it would be much faster

You could be right, but…

Those parts of the code don’t get accessed in cases when the function is called with “fin” or “eng” language argument.

And such pages were the real problem. Sure, say, Danish pages that do get into that part of the code, could’ve been even slower, but as Finnish and English pages make up about 90 percent of our traffic, those pages were the ones throwing timeouts to our logs.

So, I kinda disagree - even tho I agree that the whole listgetat thing is potentially slow. But it wasn’t the problematic part in this case.

what did the stack traces look like for the timeouts?

Cleared log data recently, don’t have much left, but here’s a copy from admin’s log analyzer:

"ERROR","Thread-1624","03/14/2019","12:07:16","controler","stop thread (2) because run into a timeout path: /(removed).cfm (/v4/includes/universal/_lib_datetime_functions.cfm).;java.lang.Throwable;java.lang.Throwable
at java. lang.Throwable.getStackTraceElement(Native Method)
at java.lang.Throwable.getOurStackTrace(Throwable.java:827)
at java.lang.Throwable.getStackTrace(Throwable.java:816)
at lucee.commons.io.SystemUtil.getCurrentContext(SystemUtil.java:993)
at lucee.runtime.debug.DebuggerImpl.addImplicitAccess(DebuggerImpl.java:767)
at lucee.runtime.type.scope.UndefinedImpl.debugCascadedAccess(UndefinedImpl.java:249)
at lucee.runtime.type.scope.UndefinedImpl.get(UndefinedImpl.java:188)
at universal._lib_datetime_functions_cfm$cf.udfCall(/vfour/universal/_lib_datetime_functions.cfm:68) 
at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:107)
at lucee.runtime.type.UDFImpl._call(UDFImpl.java:357)
at lucee.runtime.type.UDFImpl.call(UDFImpl.java:226)
at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:771)
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:756) 
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1698)
at universal.software.specific_software_cfm$cf.call(/vfour/universal/software/specific_software. cfm:1088)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:908)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:833)
at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:817)
at (removed)_cfm$cf.call(/(removed).cfm:1)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:908)
at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:833)
at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:63)
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:44)
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2405)
at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2395)
at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2363)
at lucee.runtime.engine.Request.exe(Request.java:44)
at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1091)
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1039)
at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:102)
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:467) 
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:392)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311)
at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:213) 
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:171)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:394)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Pushing the old topic here up again, as our newsletter sending code is affected by this, too. We send our newsletter to appx. 200’000 people and we do a replace for the newsletter content on-the-fly when sending it out (replacing placeholders with usernames, tracking codes, etc). With old OpenBD system, this took a while, yes, but with Lucee, the entire process takes N times longer, due the Replace() functions in use.

We’ll soon hack around this and use Java’s own string functions just to get the speed back there, but wanted to point out another example where the relatively slow Replace() function causes issues.

1 Like

Quick timing test. The top part of niceDate is taking 60% of the time. The big lang if statement is 30% and using “fi” has more replaces.
Of the top part the 2 cfloops are taking 2/3 of that time.
It looks like the MonthAsString and DayOfWeekAsString might be causing a big chunk. The rest is probably Replace.

Ucase removal didn’t change much.