tracker issue : CF-4199029

select a category, or use search below
(searches all categories and all time range)
Title:

casting switch case values causes internal exceptions, slowing down execution

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/Fixed

Reporter/Name(from Bugbase): Alexander Kwaschny / Alexander Kwaschny ()

Created: 07/09/2017

Components: Language, Expressions

Versions: 2016,11.0,10.0

Failure Type: Others

Found In Build/Fixed In Build: all / CF2018.0.0.30436

Priority/Frequency: Normal / Some users will encounter

Locale/System: / Core

Vote Count: 0

Consider the following example code:

	<cfset x = "foo">
	<cfloop from="1" to="100000" index="i">
		<cfswitch expression="#x#">
			<cfcase value="bar">
			</cfcase>
		</cfswitch>
	</cfloop>

(For the sake of simplicity I omitted further `<cfcase>` entries. It does not change the observation.)

The code example takes a whopping 5,5 seconds on my machine. So why is that? Let's profile:

	coldfusion.runtime.CfJspPage.__caseValue
		73% coldfusion.runtime.Cast._Date
		22% coldfusion.runtime.Cast._double

So CF casts all case values every time a switch runs. But let's go deeper:

	coldfusion.runtime.Cast._Date
		coldfusion.runtime.CFPage.internal_LSParseDateTime
				coldfusion.util.DateUtils.parseDateTime
					coldfusion.runtime.locale.CFLocaleBase.ParseDateTime
						coldfusion.runtime.locale.CFLocaleBase$InvalidDateTimeException.<init>
							coldfusion.runtime.ExpressionException.<init>
								coldfusion.runtime.NeoException.<init>
									java.lang.RuntimeException.<init>
										java.lang.Exception.<init>
											java.lang.Throwable.<init>
												java.lang.Throwable.fillInStackTrace

Wait, what? It's already bad enough that CF uses the old date stuff from Java (wrapped in `coldfusion.runtime.locale.CFLocaleBase`), which needs to run in a synchronized methods/blocks to be threadsafe, but no, the actual cause of the sluggish cast are exceptions, i.e. the stacktrace!

Since `bar` is not a valid/castable date, internal exceptions are thrown? What if I do:

	<cfset x = now()>
	<cfloop from="1" to="100000" index="i">
		<cfswitch expression="#x#">
			<cfcase value="{ts '2017-01-01 00:00:00'}">
			</cfcase>
		</cfswitch>
	</cfloop>

Surprise, it only took a few milliseconds to execute this. And you guessed right: because there are no more internal exceptions when casting the case value.

Casting to Double (`coldfusion.runtime.Cast._double`) behaves exactly the same by the way.

Workaround
When switching strings, you are better of using `if/elseif/else` to prevent internal casting exceptions on runtime.

Note: This affects all versions of ColdFusion!

Attachments:

Comments:

Forgot to add: I originally profiled on CF10, but other than the cast order, nothing changed in CF11 and CF2016.
Comment by Alexander K.
518 | July 09, 2017 02:36:13 PM GMT