PSA: Use CFTHREAD Cautiously

OK. For the A.D.D. crowd, here it is in a nutshell: Don't use CFTHREAD in a high-traffic scenario.

For everyone else here's the story... We recently rolled out a complete make-over to our Inventory Display UI. This included a page that lists out a typical slide-show/gallery widget.

Because the page is using a custom CFX tag we have to handle on-demand photo resizing (which it then caches the path to), the developer on the project used CFTHREAD around the thumbnail generation. So, in development, this would take a page with 20 photos and cut the render time down to about a 10th of the time.

"Oh, great!" you say, "What's the problem?". Let me tell you friend. The problem is that, by default, ColdFusion has a maximum of 10 threads to use for CFTHREAD (See the Server Settings->Request Tuning page in the CF Admin). Any threads above that setting are queued.

So, let's do some simple math: 50 people click any vehicle detail page. A car on average will have 8 photos. In this scenario we would be asking the ColdFusion server to start 400 CFTHREADs. And with a max of 10 it will start 10 threads and queue the remaining 390. Are you starting to see the problem here? ... Good.

I want you to have the benefit of my experience. So, I will tell you that this code went out like this. And for the first two or three hours we threw random timeout errors in the template for generating the slide-show. Luckily, in one of those light-bulb moments, it hit me all of the sudden that it was being caused by the thread queuing.

I was on my way out the door to lunch when it finally hit me. So, I called the office and had the developer immediately yank CFTHREAD out of that code. After the last couple of threads worked their way through the queue, that was the end of our timeout errors.

Personally, I feel like there should be some mention of this in the documentation for CFTHREAD. I read it briefly and nothing stood out to that effect. Let me know if I missed something.

Comments
Brian Kotek's Gravatar The docs say "The Tag Limit Settings section of the ColdFusion Administrator Server Settings > Request Tuning page lets you specify a maximum number of cfthread-started threads that can run at one time. When ColdFusion reaches this maximum, it queues additional cfthread requests and starts the queued threads when running threads end." which I think is pretty clear. I think I recall Damon or Tim Buntel saying that they were somewhat afraid of what people would do with cfthread, and what you've described is probably a good example of why they were worried.

Also, I was this load tested prior to deployment?

Regardless, yes, you must use threads with caution and the person who developed the code in question clearly didn't think through the ramifications of what he was doing.
# Posted By Brian Kotek | 11/30/07 11:41 PM
Chris Phillips's Gravatar Brian,

I'm almost sure that what I described is not "probably" a good example of why they were worried. I bet it's exactly what they were worried about.

And I have no defense for not load testing.

So, despite the egg on my face, I'm putting this out there so people can avoid using CFTHREAD inappropriately like we did.
# Posted By Chris Phillips | 12/1/07 12:23 AM
tony petruzzi's Gravatar sounds to me you need to rethink how you wrote your application. why are you dynamically generating thumbnails? you mention first about a slide show widget and then on demand photo resizing; i'm wondering why you would need to have on demand photo resizing for a slide show. I wondering if what you're doing is having your users upload photos and creating the thumbnails when they want to use those pictures in a slide show?

can you describe the functionality a little better for us. we might be able to figure out a way around you having to dynamically generate the thumbnails and solve your performance issue.
# Posted By tony petruzzi | 12/1/07 9:37 AM
Chris Phillips's Gravatar tony,

We have a massive application that in one code-base supports a full-featured CRM and full-featured Website for auto dealers. We use the vehicle pictures in several different sizes. So, for us to do the resizing when they upload, we would have to know all those sizes and resize up to 20 photos to a 5 or 6 different sizes. Depending on the activity on the site we may never even use those pictures. So, it would be a waste to even generate them. Then, if we suddenly needed a different size, we would have to generate the new size for tens of thousands of existing cars (maybe close to a hundred thousand. have to check on that next week).

So, sure, we could just say, here are the 3 or 4 sizes of photos that any developer has available. And maybe we even should. But, since that isn't going to happen. We will stick with the run-time (resizing/cache lookup).

And I don't want you to worry too much about us. So, I will tell you that this CFX tag is really efficient. It only has to resize them physically once to any given set of properties. Then it's just handing us a cache path. So, we can generate an entire vehicle detail page with all the content and a slide-show with 20 thumbnails and 20 full-size photos in a bout 150 ms.

I hope this isn't coming off too defensive. I really do appreciate the concern and generous offer to help us improve our code. However, this post really is what the title says, a public service announcement to let people know that there are serious (yet non-obvious) side-effects to using CFTHREAD inappropriately.

I know there will be a time when I really do need and want help and ideas. And it is nice knowing that the CF community is always there and willing to help.

Thank you.
# Posted By Chris Phillips | 12/1/07 10:21 AM
doug's Gravatar Thanks for the heads-up Chris, I knew about the queuing but did not realize the limitation of concurrent threads (10) before queuing. Fortunately, I have not chosen to use cfthread in any of my code and have not experienced the issue.
# Posted By doug | 12/1/07 12:37 PM
Mark Mandel's Gravatar Chris,

Just a thought, but when you get around to load testing you application (as I'm sure you now will ;o) ), have a look at what happens if you keep the cfthread'd code, but simply up the number of threads on the pool. Maybe put 500 in there, and see what happens.

I would be curious to see what high numbers of threads in the pool would do - you may find you can keep your system performance on a high load with a large number of threads in the pool.

Let us know how you go.
# Posted By Mark Mandel | 12/1/07 4:25 PM
Troy Allen's Gravatar Just curious...what WOULD be a good example of when to use CFTHREAD?
# Posted By Troy Allen | 12/2/07 8:15 AM
Miles's Gravatar Firing off an asynchronous request is one good example...
# Posted By Miles | 5/14/08 9:34 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.6.002.