After pouring weeks of personal time in my ColdFusion custom tag DSL for HTML emails, I was a bit gutted when I went to apply the methodology in my local InVision code only to find out that it was running very slowly inside of my Docker for Mac container. It turns out, when using the
<CFImport> tag, Lucee CFML is doing a massive amount of File IO (Input/Output), resolving the CFML file on every invocation (which I've filed as a bug). And, File IO is notoriously slow in Docker For Mac. Which begs the question: how does the local File IO penalty compare to a production Lucee CFML server which is also running containers but is much closer to the metal? It turns out, the File IO in my Docker for Mac is 68-times slower than it is in production.
CAVEATS: This is not meant to be a blanket statement for all Docker setups. Nor is it meant to be extrapolated into all forms of File IO. This is very specific to my local setup, my production setup, and the type of Lucee CFML code that I am running.
To test this, I took my previous demo code and made it a bit more dynamic, allowing me to pass-in the number of iterations as a URL parameters:
<cfimport prefix="tags" taglib="./" /> <cfparam name="url.count" type="numeric" default="100" /> <cftimer type="outline" label="CFModule"> <cfoutput> <cfloop index="i" from="1" to="#url.count#" step="1"> <cfmodule template="./MyTag.cfm"></cfmodule> </cfloop> </cfoutput> </cftimer> <cftimer type="outline" label="CFImport"> <cfoutput> <cfloop index="i" from="1" to="#url.count#" step="1"> <tags:MyTag></tags:MyTag> </cfloop> </cfoutput> </cftimer>
And, as with my last demo, the
MyTag.cfm file does basically nothing except output some static text. My goal here is not to test the ColdFusion custom tag itself, but rather the cost of invocation:
<cfswitch expression="#thistag.executionMode#"> <cfcase value="start"> . </cfcase> <cfcase value="end"> </cfcase> </cfswitch>
Once I deployed this code to production, I then went about testing each environment 5-times (ie, just refreshing the page, recording the numbers, and trying again) using 10,000 iterations. Once I collected all of the numbers, I put them in a Google Spreadsheet and crushed the averages. Here's what I get:
Oh sweet chickens! When we compare the average execution time of the
<CFImport> performance, the local Docker for Mac code is 68-times slower than the same code running in my production containerization.
Furthermore, within the local Docker For Mac environment,
<CFImport> is 114-times slower than
<CFModule> (due to the File IO). In production, that same difference calculation is just under 2.4-times slower.
On the one hand, it's shocking that Docker For Mac has such crazy-slow File IO. But, on the other hand, this is great news for me, because it means that my ColdFusion custom tag DSL for HTML emails is actually a viable solution! I just have to accept the fact that it will be slow locally and much faster in production!
Want to use code from this post? Check out the license.
If anyone wants to look at the raw performance numbers, here's what I put into the spreadsheet:
Docker For Mac →
This is great news!
Are you using a Windows or Linux Server in Production?
I presume you are using Windows, in production, with those i/o improvements.
It would be interesting to see how your system runs on a Linux Server, considering Linux is fairly similar to Mac.
I don't mean to put a downer on this, but I know that CF folks are using Linux more and more, these days, so your system might need to work on a Linux server, as well?
It might be worth testing your system on a Linux VM?
I believe that we are using some form of Linux in production. But, I don't know enough about Docker to see what is going on. In our Dockerfile, we are building off of one of the core Lucee images, I think. But, regardless, I'm super excited about this!! :D
OK. That's very interesting.
When you complete the project, I can put it through its paces on both Windows 10 and Windows 2012R2 [web server]! I don't use Docker, so it should be fast anyway.
Sounds like a plan :D