Caching Repetitive UDF Access to Request Scope Using Argument Stringified+Hashed Key

James Moberg - Mar 13 '23 - - Dev Community

While viewing FusionReactor logs for a ColdFusion app, I noticed lots of repetitive JDBC entries in a request that contained the same exact SQL statement and was taking 42ms per execution. I checked the UDF that was performing the query (using QB) and the query was configured to be cached for 5 minutes... but overhead-wise, it was still taking 42ms each time. The "Number of Queries" for the request was 57 and most of the queries were similar cached 40ms lookups and it started adding up to 1,452ms overall. I wondered if there was anything I could do to add self-contained caching to UDFs that could benefit from them. I didn't want to save the response to the session (YIKES! I've seen some code that does this) or use cachePut/cacheGet since the caching only needs to live for a single request of "repetitive access".

I've been playing with the java hashCode() function to convert strings to a unique signed integer and wondered if I could stringify the arguments passed to create a cacheable key and very temporarily store the result in the request scope. This works (for me) and I'm happy with the results, but I wonder if there are any potential issues or side effects that I'm not considering (besides the rare chance of hashing entropy).

Here's a sample UDF with some slow/fake business logic (emulated using sleep(1000)). The first request is normally slow (as expected) whereas all repeat accesses with the same exact arguments are 0ms. I believe that this approach may also work in environments that use multithreaded processing on a single request, but I'm not 100% sure. (ie, in a multithreaded environment, would it be recommended to use CFLock with request scope locking?)

Source Code

https://gist.github.com/JamoCA/62f8535cfcf5dacd4e7f5ea678038330

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .