Damon Cooper's BLOG
Viewing By Entry / Main
September 13, 2006
Updated CFTHREAD Proof Of Concept for ColdFusion 7.0.2

Below is an update to the original CFTHREAD Proof of Concept (POC) that adds experimental multithreading support to CFML on ColdFusion MX 7.0.2 that Adobe Computer Scientist and ColdFusion Engineering Team developer extraordinaire, Rupesh Kumar put together in his own time for you to play with. Our development engineers are called “Scientists” at Adobe which is cool because it means that we understand the importance of experimentation.  And like all good scientists, we hypothesize and test – some things make it into the product, others don’t – but we’re always innovating. 

This POC works with CF 7.0.2 (Standard or Enterprise).  While you can do multi-threading and asynchronous CFML with these POC tags, they don’t provide any of the fine-grained threading control you have with ColdFusion Event Gateways and the Asynchronous Gateway, for example.  So you don’t get thread pooling, control over how many worker threads can be active or pooled, metering on Gateway messages In/Out, or any of the other advanced capabilities of the Event Gateway architecture on CF7, but they do the basics: run stuff asynchronously in separate threads and allow for the use of local (thread-local) variables, allow access to shared scopes, etc.

A note on the simple example: you'll want to modify both templates to copy a file (I use a “C:\baseline.txt” file) that exists on YOUR system to a directory that exists on YOUR system (I used “C:\____WORKFOLDER”).  I’d recommend turning on debugging so you can see the execution times yourself as well (much more dramatic that way). Also note that spawned threads shouldn't count towards Simultaneous Threads slots of the CF Server, so you shouldn't need to adjust that setting to accommodate your extra threading.

The CFTHREAD POC enables you to spawn a new thread and optionally wait for a thread to finish. A thread can be spawned using and a thread can join with another thread using .

This update will be the last for the CFTHREAD POC, but it does address some of thread safety issues of the first CFTHREAD POC, and has the same syntax. The two small additions to this updated POC are that a) you can pass any variable to the thread tag and b) any variables defined in the thread tag are local to the thread.

Thread Safety
==========

Each thread has its own local scope and any variable that you define inside the thread goes into that local scope. This is very much like function local scope except that you don’t need to prefix those variables with 'var'. A page scope or other scope variables will be accessible inside the thread using the appropriate prefix like variables.xx or request.xx. CFTHREAD tag also allows passing any variable as attribute to the tag. The attributes thus passed can be accessed using attributes.xxx.

Apart from thread local scope, there is a special scope for thread called "thread" scope. this is a scope in which only the owner thread can write but all other threads can read values from it. This scope can be accessed by ".xxx". The owner thread can also access it using 'thread.xxx'

A thread can put some data in its scope and it can later be retrieved.

Browser Output and Error Handling
========================

CF code written inside CFTHREAD can not write any content to the browser. So any output written using from 'CFTHREAD' will be accessible inside the 'thread' scope using "thread.OUTPUT" or .OUTPUT

Similarly, any error thrown from a body will not be sent to the browser and will be available in thread scope using "thread.ERROR" or .ERROR

Syntax
=====

1) To start a thread:

  
           
           
           
           
           
           
 

This will spawn a new thread and any content between tag will be invoked inside that new thread.

2) If you want to wait for this thread to finish, you can use

  

If thread 'th1' is already over by the time you reach here, it will have no effect. Otherwise it will wait for th1 to complete. One important thing about this POC is that you can wait for only user threads that have been created in that request. So you can not use join for any arbitrary thread in the VM, for example. If you only want to do some operation asynchronously and do not need to wait for its completion, you need not use .

3) To retrieve a value put in a particular thread scope, simply access that scope variable. So you can use th1.x to get the value of x kept in th1 scope.

4) CFTHREAD does not provide a way to sleep. however if you want to do it, you can use

  
  

This code lets the current thread to sleep for 10 secs (10000 milliseconds). For example, if you want 'th1' of above example to sleep for 10 sec, this code snippet will go inside

CFTHREAD POC Setup
=================

The zip file contains two other files

- cfthread.jar - This file should be kept in /lib/updates
- taglib.cftld - This should be kept in /wwwroot/WEB-INF/cftags/META-INF. To be on the safer side, you should backup your own original copy of this file.

Restart your server and you should be ready to try out the POC!

DOWNLOAD CFTHREAD POC & SAMPLES ( 101K)

Caveats
======

Once again, just to be clear, this POC is not a CF product feature at this time, has not been properly QA'd, contains bugs and is unsupported. There is also little chance that should a POC evolve into a feature that the tag syntax will not change (perhaps drastically) in the future, and there are no plans to update the POC as future major versions of CF come out.  CFTHREAD may or may not make it into a future release, but that partly depends on feedback from you, our customers.

Enjoy! And thanks Rupesh!

Damon

Comments

I'd just like to say thank you. :) I'm really excited to see these updates.


Really nice, thanks. Hopefully I look at moving some Java back to CF now.


This is just awesome. Thanks so much! I have a lot of plans in store for this little fella. I hope it makes it into the final release :)


Just commenting to say that I would definately use this if it were a product feature. There are a number of slow queries (yes, optimized as much as possible) and calls to external executables that I would love to call in threads.


Thanks! I look forward to seeing if I can run parallel queries in this version. (I assume it was choking due to a shared CFQUERY variable? Not sure.)

r0xxx0r.


Having provided lots of feedback on the initial POC, I'd just like to thank Rupesh for really listening to feedback and taking the time to implement the feature requests.

Hopefully Adobe will see this as a successful "experiment" and might start releasing more POC in the future, that based upon their reception by the developers, eventually make their way into ColdFusion.

I personally really hope that CFTHREAD/CFJOIN make their way into Scorpio.


I can see the point of threading in heavy duty languages and major processing etc etc, but what is the point in CF (though don't get me wrong, I like the POC).

My only thing is I can think of no reason why threads are required in software like ColdFusion; major data manipulation etc should be managed where it came from or at an off peak time - perhaps this is where threading is most usfull by reducing the priority and thus adjusting the timeouts allowed??

I refer this to Brian's post; re the slow running queries example; if queries are slow running (regardless of optimisation) then threading is avoiding the real-time problem and it is time for a application rethink. One slight blip and slow running calls etc will cause the whole thing to fall down - and to then add the complexity of threads?

dunno. Keep it simple I say


BAH:

There are times when the slow executing processes are out of your control. For example, Verity indexing can be very slow on servers w/a large number of collections.

This is a perfect example of where being able to spawn off a thread to handle the indexing is useful. There's no reason for the user to wait 30 seconds for the content to index. Just spawn a thread and display a message to the user.

Of course I can think of plenty of similar examples where it's useful, this is just one example.


Dan beat me to it, so I just want to ditto it. No matter how well you code or architect, there are some things that are just going to be slow. Period. Or possibly slow, like http requests.


BAH: If every part of the application is under your control, there are still times when you have long running processes, but in my case, I have to make the best of a bad situation to get information out of the ERP system over a long distance database link and create the required reports. There is also just an awful lot of data to deal with. You may live in an ideal world; unfortunately, I do not and threading makes hard stuff easy.


Brian, db links, ouch, I know the feeling - I'm not saying that cfthread is a bad idea perhaps this was misunderstood juding by the jumpy responses:) I can see it being misused with Cf apps all over the place for any poorly performing applications. Wouldn't it be the same to just filter the entire ColdFusion experience through spawned threads and thus serve up "please wait..." messages followed by the actual response?


BAH:

You know it might be abused, of course I think there's a lot of CF functionality that gets abused. It's part of the problem any time you have a programming language that's easy to learn.

You can pretty much take anyone w/a comfort around computers and have them build their first ColdFusion application ("Hello World") within a few minutes. Getting them to really learnd programming is a whole other process--one that takes years.

So well you're probably right saying people will abuse CFTHREAD to just make slow processing code seem fast, they're still going to be in the same boat and still have issues with their servers.

However, in those times when developers do truly understand what's going on and the problem is out of their control, or has been reduced as much as possible, it's going to be very handy.

I definitely see many useful ways of using CFTHREAD. I have a couple month end reports that will be spead up immensley by threading. I have 2 separate long running queries. Right now I have to wait for Query A to finish and then run Query B. With threading I can fire them both of and then use QoQ to join them when they both respond. (These are separate DSN on different servers.)


Dan, I think this can be applied to multiple features. CF easily lets you (attempt) to read in a multi-gig file all at once. CF easily lets you cache queries (when the person should have used better sql perhaps). At the end of the day, the developer has to take some responsibility to know _why_ he is using so and so tool and if it is appropriate.

I think cfthread will probably not be abused as the other examples I gave above, simply because some people just won't get it, no matter how easy it is.


lads, I think I'm understood now :) I only came accross this post when looking up details of the "next" release of CF and future enhancements (blogged by Mr Corfield at corfield.org on 24/7/2006). Raymond's comment about _why_ a developer would do something is the issue I have with the cfthread. Apart from that, congrats to the guys who created this.


Bah, can you explain? I didn't give concrete examples here. I did stand up for it (saying how other htings can be abused, the developer needs to be responsible, etc), but I don't think I gave an improper example. (If I did, let me know.)


Awesome,

This will helop with some very long running requests I'm trying to fix right now.


Hi!

Sad to say, but after installing tag "per instruction" I get following error:

You are using tags whose name begins with CF, but the tag is not registered with Neo. Either the tag is not completed yet, or have you been playing with the configuration?

Unknown tag: cfthread. ColdFusion cannot determine how to process the tag cfthread because the tag is unknown and not in any imported tag libraries. The tag name might be misspelled.

Any help is highly appriciated...


@Alex:

Are you sure you updated the correct taglib.cftld and restarted the server? That message sounds like the correct taglib.cftld file wasn't updated. You will also need to recycle the CFMX services for the change to take affect.


to Dan G. Switzer

Yes. I placed both files to the respective locations and restarted CF server. It didn't work. I installed both files once again and rebooted box. No luck...


Opppsss... Probably I know the source of the problem... Installed on one box, testing on another. Never mind! Thanks for prompt reply! :)


Hmmm... Another question/problem... Hope this time I missed something too...

If I put code into an include, then thread scope is no longer accessable/exists.

include.cfm ---- ----

code: ---- ----

then ---- #blah_blah.blah# ---- throws error "blah is undefined in blah_blah"

Did I miss something once again...?


@Alex:

You must remember that the whole point of cfthread tag is that the information in the thread is processed asynchronously. That means as blah_blah thread is being processed it's also processing your cfoutput statement. Since the two pieces of code are running simulatenously, there's no way to guarantee the thread is done running.

That's why you need to call the cfjoin tag. To ensure that the core template waits for the thread to complete.

Try calling the cfjoin tag before the cfoutput and see if that doesn't resolve the issue.


to Dan G. Switzer It doesn't. In my actula code I have cfjoin. It looks like ---- #evaluate(variables.thisThreadName & ".success")# ----


Hmmm... Seems like things went from bad to worse...

I tried to escape this very bad situation by moving cfthread tag into inclides and got following error

Error Occurred While Processing Request

Routines cannot be declared more than once.

The routine "_cffunccfthread_cfping_ACE2ecfm16893343631" has been declared twice in different templates.

I checked value of the cfthread name attribute. Values are definitely different.

Any help is HIGHLY appriciated...


LOS ANGELES, July 5 Pomegranate juice may help counter erectile dysfunction, according to findings by the University of Southern California. http://www.opencps.org/Members/bestonline/dysfunction-erectile-pills/dysfunction-erectile-pills.html Dr. Harin Padma-Nathan, of the Keck School of Medicine at the University of Southern California, conducted a randomized, placebo-controlled, double-blind, crossover pilot study to examine the efficacy of pomegranate juice versus placebo in improving erections in 61 male subjects.


A glass of pomegranate juice every day may help manage erectile dysfunction, suggest results from a randomised, placebo-controlled, double-blind, crossover pilot study. Dysfunction erectile pills "Efficacy and safety of pomegranate juice on improvement of erectile dysfunction in male patients with mild to moderate erectile dysfunction: a randomized, placebo-controlled, double-blind, crossover study"


[url=http://test.com]Test[/url]