Viewing By Entry / Main
July 21, 2006
CFTHREAD and CFJOIN Proof Of Concept Tags

Our development engineers are called “Scientists” at Adobe which is cool because it means that we understand the importance of experimentation.  Like all good scientists, we hypothesize and test – some things make it into the product, others don’t – but we’re always innovating.  Here’s an example that Rupesh Kumar (CF Computer Scientist / Software Engineer) did on his own time after talking with a number of our customers about asynchronous processing in CF….not a lot of bells and whistles, mind you, but still a great Proof Of Concept of the CFTHREAD and CFJOIN tags.  I’ve also included a couple simple example templates to demonstrate the tags.

The first example copies a file 50 times files + sleep 200ms each time, and the second example launches 50 threads with CFTHREAD to do the same work and join back up at the end of the page with CFJOIN.  

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.

Running the serialized example with debugging enabled yields this execution time block:

Execution Time

Total Time

Avg Time

Count

Template

10072 ms

10072 ms

1

C:\Inetpub\wwwroot\threadsynch_serial.cfm

0 ms

 

STARTUP, PARSING, COMPILING, LOADING, & SHUTDOWN

10072 ms

 

TOTAL EXECUTION TIME

red = over 250 ms average execution time

And running the CFTHREAD example with debugging enabled yields this execution time block:

Execution Time

Total Time

Avg Time

Count

Template

235 ms

235 ms

1

C:\Inetpub\wwwroot\threadsynch_cfthread.cfm

0 ms

 

STARTUP, PARSING, COMPILING, LOADING, & SHUTDOWN

235 ms

 

TOTAL EXECUTION TIME

red = over 250 ms average execution time

To be crystal clear, this little POC is not a CF product feature at this time.  This is just a simple and unsupported engineering Proof Of Concept.  I’d personally welcome your feedback and comments and I’d love to hear how folks might be able to use such functionality, but the POC’s are unsupported.  This is also no guarantee that the tag syntax will not change (perhaps drastically) in the future, and we have  no plans to update the POC as future major versions of CF come out, etc, etc.  CFTHREAD and CFJOIN tags may or may not make it into a future release, but that partly depends on feedback from customers.

One known issue/observation in playing with this personally: there appears to be a bug where if you don’t rejoin (using CFJOIN) all the threads you've spawned by the end of the page or you get a “500 Null” error (at least with my example, if you comment out the CFJOIN loop).  However, calling CFTHREAD (once) and skipping the CFJOIN appears to work fine.  Just so you’re aware.  You still get amazing parallelism as demonstrated above, even if your page waits for all threads to complete. Maybe if there’s interest we could fix that one thing, but for now, do play with these POC tags and let me know if they’re useful to you.

DOWNLOAD CFTHREAD POC & SAMPLES  (74k)

Damon

Comments

Damon,

It's great to see this released. This has been something I've really been looking forward to in CFMX. While the Event Gateways are awesome, being able to asynchronously process information in a new thread is really helpful in some tasks--such as using to update a collection (which is a time consuming process that the user should not have to wait on.)

However, since this is a "non-support" project, what are the chances of getting the source code released? That way the community can fix any potential problems with the code (such as the 500 null errors?)


That is great news ... see you guys did go to the BlueDragon session at CFUNITED! :)


Now now ...you can't give BD credit here. Google this topic and you will find many enhancement requests by yours truly for this exact feature. Wish I trademarked the tag names ;)

Damon, you have no idea of how great your timing is on this ...I JUST started rolling my own implementation to support a new project in-house. We've used a homegrown CF reporting platform for years here but have always missed the more advanced management features of the pricey reporting/BI packages out there... In a nutshell we're creating a management/monitoring console in Flex 2 with data services ...with a report manager (CF) which controls/monitors threads on the system. Very, very slick! :)

I also love the fact you guys are willing to dump this out there even when it's not official. It's the best way to get our feedback!


BUG: Along w/the 500 Null error--I also notice that it doesn't always complete all the threads. I've modified the code slightly to write a new file by looping through a string.

It seems to be pretty random how many threads actually complete, but in very unscientific testing the most I've seen is 28 out of the 50 threads be completed.

If we had the source code, this is a problem we could probably resolve the problem ourselves. :)

Here's the modified code I'm using. It just requires a "tmp" folder in the directory which the threadsynch_cfthread.cfm resides.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



#Server.ThreadsCounter# files now written.


Work Complete!


Would be neat to have meta data available on each thread similar to cfhttp. For example, myThread.elapsedTime, when read, would return the elapsed time a particular thread has been running.


Stacy, you aren't the only one that has asked for this feature - this has been on the cards for a long time for CFML.

Naturally, with the EventGateway side of things, you could achieve the same results. But why force a CFML developer to drop to Java, when you have this beautiful tag based language to express your solutions in. This has always puzzled us.

The BlueDragon implementation has a whole suite of tags and functions to support this feature set, which also runs on both .NET and JAVA platforms. There is a lot of management to do when you start giving developers this ease of access to a very powerful set of processing directives.

If you think a simple CFLOOP can take down a server, then thats nothing when you give them access to spawn threads at their hearts content! :)


Well you know what they say ...With great power comes great responsibility. ;)


Actually, Stacy, according to Damon's own statements on the CFTALK mailing list, it is accurate to credit the timing of the appearance of these tags on Adobe's attendance at the New Atlanta keynote at CFUnited. And you might consider why it is that Adobe is "dump this out there even when it's not official." It is reasonable to consider that perhaps they would have taken a different approach were these tags not announced for BlueDragon 7, but of course only they can tell you the real story there!


this is a killer feature to have


Guys c'mon. Was intended as a lighthearted humor.

http://www.houseoffusion.com/cf_lists/messages.cfm/forumid:4/threadid:26690#134416

In all seriousness I don't particularly care where the innovation stems from. If BD generated the initial buzz, great, kudos to competition! How about we avoid any debates and just try out the tags in question? :)


Alan: No Java required by CF7 customers to do this stuff today with Event Gateways. Simple CFML and configuration of an Async CFML Gateway Instance in the CF Administrator.

WRT posting source: maybe. SWe'll see. Right now we're focused on Scorpio with some important milestones coming up, so we're very busy, but I'll see f we can't tweak the main issues with this (need to use CFJOIN + no "arguments" argument to cleanly pass in args).

Dan, not sure about your missing threads. Do you get the number of files copied you expect? Watching threadcount on the CF/JRun process is not an accurate way to see if all threads complete...the VM does it's own thing at the OS level.

Thanks for the comments guys...love to see any examples of how you might use it.

Damon


Any way to terminate a thread?


Stacy: no way to kill threads with this POC unless you do it yourself with Java API's somehow.

Damon


@Damon

No, I'm not seeing the the number of files created that I expect (at least not all the time) and that's even *with* the tags in there. Sometimes I'm evening seeing the 500 null message even w/the tag in there. This seems to happen when I do a very simple load test.


Then definately my first enhancement request.

Here's high level description of what I'd like to do:

Create a facade that can accept incoming report requests, spawn a new thread, execute the report request. (this use case we're talking about offline report generation so delivery mechanism is not part of the equation)

From a management perspective, I need to be able to manage these threads. Perhaps methods to retieve meta data on each or all threads (running time etc) and perhaps the ability to "kill" a thread if so required.

Anyway, just filling in the blanks so you guys have an idea on a potential use.


Thanks for the additional comments, Stacy! No offense taken on my part at all--I just wanted to set the record straight on the inspiration for these tags. But here's the real reason I'm writing now: I am so glad that you get that competition is good for customers, Stacy! Sadly, many in the CFML world do not. And that's too bad because whether you ever use BlueDragon or not, the reality is that what we at New Atlanta do with that product can impact you as a ColdFusion user, as this particular situations so aptly demonstrates.


This is an exciting development! After seeing Blue Dragon's presentation at CFUnited I was hoping Adobe would add this to ColdFusion. There are so many uses for multithreaded programming and cfthread/cfjoin are much more usable than async. event gateways (IMHO).

So here's my vote to please continue development of this feature and make it a regular supported feature of the language!

Thank you.


UPDATE: Ok, I've continued to play around with this and for me, it's highly unreliable. Even if I lower the number of threads down to 10, I still get erraditic results.

For example, I just ran the test script again and I get no error messages--but I only get 6 files created.

I've even tried using a static named lock on the calls to see if it's a threading issue w/the file operations. That didn't seem to change the behavior at all.

I've also check the CFusionMX7\runtime\logs and CFusionMX7\logs for any related errors that might be generated, but I'm not finding anything--other than when I actually get the 500 null error.


I've been saying since before day 1 that async processing should be in every version of CF (maybe limited in pro) and the interface to it can be made 'nicer'. I'm happy to see this put out and I'm hoping to see more of these types of experiments/posts.

Now about those enhancements to CFCs... :)


Isn't dangerous to create an infinite loop over CFTHREAD tag? Does the POC handle this?


I'd like to say I can think of dozens of uses, especially when it comes to our use of Verity, Reporting and Customer File Management. I'm salivating! Damon, please push for this.


What about a CFTHREADGROUP parent tag? Perhaps that is what would provide meta data on child threads etc .. but more importantly, allow you to set some limitations like max threads or what not.


I am having the same issues as Dan. Not all the files are copied. The threads seem never to "cfjoin" back up, yet it reports a success.


*** DAN'S UPDATE***

Ok, I've gotten a little further. It seems the variables are not thread safe.

The problem I seem to be running into is any variables within the tag will be affected by changes by the other threads.

What it seems we really need is a "thread" scope which is unique to each thread. I've tried using:

The problem is, once inside the running thread, the variable "threadname" is no longer thread safe. So that doesn't work.


Actually you do not see all the files created because the threads were not given the correct file name to create. Its a synchronization issue. If you do a system.out.println for the file you are writing, you would notice that multiple threads are writing the files with the same name. I will soon provide a way to fix this synchronization issue.


PS - I also think the 500 nulls are being generated by the fact that a thread is trying to access some variable in some indeterminable state.


@ Rupesh

What I'd love to see if is that you use a scope called "thread" inside the tags to make thread safe variables.

Outside of the tag, you could use the thread name.

For example:

#dansThread.name#
#rupeshThread.name#

I think that would take care of the threading issues.


That's actually the behavior I was expecting, so I'd agree - haven't tried this yet tho, still rebuilding my PC :(


@ Rupesh

Actually, after rethinking a bit, I'm wonder if maybe all variables should be local to the thread, and you use like the Caller scope to access variables from the core template.

Also, I'm wondering if there shouldn't be a thisThread scope that contains information about the thread (ie. thisThread.name)

These changes would allow something like the following:

#x.message#

Does this makes sense?


I understand that these tags do need quite a bit of work and some POS (Proof Of Stability) :-P, but I am glad to see that BlueDragon and Adobe, whether by competitive interest or just paying attention to their customers seperately are bringing these things up.

Adobe and New Atlanta both develop solid products for CF and I just want to keep seeing the language get smarter, faster and even more capable. I have to admit, I have been worrying a bit about programmatic / development improvements to CF losing concern amongst all the other things going on.

Thanks again and let me know where to put my vote for getting these tags in the next release!

Mike.


This is great - I'm definitely going to download the sample and play with it! I can't wait to see this tag in action once it's been worked over by th Adobe CF team. Everything I've seen come out of Adobe/Macromedia has always been top notch. I'm just finishing up my graduate degree and have a strong foundation in algorithms so if this tag gets integrated with CF I'd really be interested in seeing what kings of limitations it has. Thanks for the continued improvements to such a great language!


I Like this alot. two thing's I'd add:

1. Meta Data, Really like that idea alot, get timeelapsed and stuff, etc.

2. Custom Error catch for this. so we could perhaps

... thread did not process

that would be neat as well.


I say keep going forward with this work. We run many reports for our customers. Some take several hours. It would be fantastic to be able to run these simultaneously on worker threads and save - most likely - hours of time on this task.


These are exactly the kind of advancements we need in ColdFusion. Please urge those at Adobe to include CFJOIN and CFTHREAD into CF8. We would love it!


this can also be achieved by using cURL and the cfexecute tag. (good when version LTE 6.1)

http://curl.haxx.se/


@Dan The thread safety issue isn't necessarily an issue with cfthread, it's more an issue with the way variables are scoped in coldfusion. You will have the same issues in functions if they live in a shared scope(session, server, application). Think of the parent thread as the shared scope and the cfthreads as functions within the scope.

It's easy to make your threads "thread safe" by taking advantage of something where you can control scopes (like cffunction). I've posted a code example on my blog to show how you can take advantage of this.

http://www.schierberl.com/cfblog

On a side note, if I had a vote, I would say that threads should have their own scope and variables must be passed into a thread as an argument, just like a function or custom tag.


@Mike

I posted over at your blog. Well it address newly declared variables, it does address passing in variables in which you need a snap shot of the value at the time where the thread was created.

For example:

In the above example, there needs to be a way to make sure that in "thread1" the value of Y equals 1, the value in "thread2" equals 2 and so on.

At this point, I've seen no way to do that.

Maybe it's going to be necessary to have an "input" attribute for each thread which will allow you to put in some static snapshot of a variable which you can use in your thread.

I wonder how NewAtlanta handles this.


Dan,

You're right, you got me... passing a value as an argument still treats it as being passed by reference. Guess I need to give another note to giving threads their own scope. From what I can remember from cfunited, the New Atlanta approach is to give the thread access to tag attributes, application scope (maybe server too). Here's what Vince used as an example.

I'm guessing it would look like


Just a small question - but how does one get themselves off this spam-blog?

It's a pretty poor affair when there is no option to stop receiving alert emails just because I happenned to leave a reply!!!

Make the madness stop someone PLEASE!


Dan et.al,

The thread-safety issue is most likely just an implementation detail (a.k.a. "a bug") in this particular version of the cfthread lib that needs to be worked out. The base Thread class in Java already allows for simple "thread-specific data" (e.g. the name of a thread), and therefore it should be possible to create a data structure of some sort to track unique user-thread instances in order to avoid "the clobber scenario". You could even subclass Thread if you need additional thread-specifc data.


@Dante

I'm totally aware of this--which is why I'm posting comments to help them be aware of issues. I'm not "condemming" the code, just trying to make people aware of the issues in using the tag in the state it is now.

It can still be very useful in certain situations (such as spawning off a thread to index a verity collection) where maybe the state of the variables are read-only and you can create static variables for the thread that won't change.


@Dan

Understood. I was just trying to say that a fix should be possible. As you said before, it'd be nice to have the source. :-)


Someone said something about the wrong number of files being generated... I don't remember if anyone replied to that comment or not.

I moved the closing cflock tag to just below the sleep call, so that the copy operation was locked as well as the thread counter. This resulted in a slightly slower running page, but in a proper sequence of generated files.

Laterz, J


Correction:

If you move the closing tag to just below the file copy operation and just before the thread is put into sleep mode, it runs blazing fast but doesn't use the same file names.

Laterz, J


If you comment out the cfloop that runs the joins, one of two things happens:

1) the code runs, the files get created, and no output is generated for display (all 50 files are there but nothing is on the screen like X FILES CREATED) 2) the code runs, all the copies happen, but the screen sees an InvalidState error and a cf stack trace

Just wanted to say something before I forgot. :)

Laterz, J


This is great, hope it makes it as a supported feature of CF8. Wondering if someone could explain this to me... If it is possible to spawn off N number of threads why is is such a critical performance tuning practice to tune your applications simultaneous request for CF? How is creating these threads different than the simultaneous request?


Damon, this tag rocks.

You mention that skipping is okay if you call only once.

However that doesn't seem to be the case.

I loaded the following code 10 times. It produced the expected screen output 9 times, but produced only 4 files.

Operation complete


(it still works fine if I do the cfjoin afterwards, but it doesn't suit my needs to wait for the thread to complete =)


Seriously though - how do i CFABORT this blog thread?

This is major spam time, and i can't see anyway to unsubscribe myself from this (cf?)thread!


For those of you who were following the CFTHREAD POC, I've posted an update here:

https://dcooper.org/?mode=entry&entry=A71F310C-4E22-1671-5E287AE8918A048B

Enjoy!

Damon


Does this POC not handle CFSCRIPT? I have tried playing with it using CFSCRIPT within the CFTHREAD tags and it would seem that the CFSCRIPT is simply not processed.


@Andrew:

While not an "official" answer obviously, the CFTHREAD tag is currently on tag based. Because of the nature of the tag, there would be no way to wrap it up as a UDF, so you currently would not be able to access it via CFSCRIPT.

They'd specifically have to support some kind of CFSCRIPT syntax--which would end up probably being pretty klunky.

However, you could always use CFSCRIPT inside your CFTHREAD tags. Just break your CFSCRIPT calls up.


Yeah, not sure if/why cfscript wouldn't be processed inside the cfthread tag. It def works in Scorpio.

In Scorpio, fyi, CFJOIN is no more and this tag has been dramatically enhanced.

Thanks to everyone for their feedback, this has been very valuable to us, and hopefully it has been for you guys as well!

Damon


antique gas stove asp hosting seattle site web antique child rocking chair antique classics antique car club antique replica phone http://agoal.strefa.pl/escort275.html http://agoal.freeunlimitedweb.com/escort856.html http://cecrr.gigazu.net/escort360.html antique bb gun antique electric lamp antique door glass knob antique collectible com ebay cheap free web site hosting antique piano price http://airasa.10fast.net/antiquefb2.html http://agoal.w8w.pl/antique099.html http://membres.lycos.fr/agoal/antique286.html


nokia 3390 cell phone accessory nokia software download free nokia 6260 review catz pussy cell download free nokia phone theme tickling italian feet http://jerteris.1afm.com/escort73a.html http://www.gindos.fsfn.net/escortfbe.html http://www.gindos.fsfn.net/nokia6c7.html http://ainaae.brmz.com/escorte4f.html


6280 download free nokia food vitamin b12 download free n70 nokia theme cooking diabetic free recipe http://whitestruct.gigazu.net/recipeb07.html http://www.werxcv.builtfree.org/recipe4d6.html http://auraspase.100webspace.net/recipeadb.html 3250 download free nokia theme juegos de mini clip vitamin k fact 6270 free nokia theme http://anyfind.gbs.me/pussy966.html http://anyfind.k2free.com/pussy975.html http://anyfind.za.pl/pussy251.html