[Home]ExecutionEnvironments

FlowBasedProgramming | RecentChanges | Preferences

The three implementations of FlowBasedProgramming done at IBM (all mainframe implementations) were all non-preemptive, also referred to as "cooperative", or "green threads", where control could only be switched between threads at a service call (like IBM's CICS). In these implementations, suspendable services test if that service (e.g. a receive or a send) can be satisfied, and if not, control is given to another ready thread, or the whole program is suspended until a thread becomes ready. The disadvantage of this approach is that you may have some long-running non-FBP service which will tie up the whole application until the service completes (because the scheduler doesn't "know" about it). The advantage is low overhead and ease of implementation in many environments. IBM mainframe software provides a number of so-called "basic" or asynchronous I/O services, which allow I/O to be started, after which a different thread can proceed. At a later time, the system can test if the I/O has completed, and resume the original I/O-issuing thread if it has - this means that only one thread will be suspended while the I/O takes place. So this meant that we were able to build efficient applications using asynchronous I/O, but couldn't multithread with Sorts or SQL calls.

This is similar to our cooperative implementation of FBP written in C (which has been used for production work), except that the whole application hangs every time we us a standard C I/O service. I believe there is an async I/O facility available for C, which could (perhaps partially) address this problem, but we haven't done any experimenting with it.

The other type of FBP implementation (asynchronous) is used for the Java implementation (JavaFBP), and now for our C# implementation (C#FBP). In this case, every FBP thread is an instance of the Thread class, and synchronization only needs to occur when working with inter-thread Connections. Control can switch between threads at any point, but only Connections need to be protected (plus a couple of other minor features). In the Java implementation, we use the Java "synchronized" function to control this. This version (http://www.jpaulmorrison.com/fbp/JavaFBP-2.4.jar) is available on my web site, and also on SourceForge. The C# implementation of course uses the "lock" function, and is available on SourceForge, and also on my web site, at http://www.jpaulmorrison.com/fbp/CsharpFBP-2.3.zip.

Note on max. number of threads from SvenSteinseifer:

Regarding the use of threads: A quick search on the internet revealed that the maximum number of threads depends on the operating system and the available memory. I've attached a test program I found on the net which tries to spawn as many threads as possible. On my machine with 2GB ram, an out of memory error occurs after creating 7400 - 7500 threads. It is possible to limit the stack size using a command line switch. To limit the stack size to 100kB, one would issue the following command on the command line: java -Xss100k MaxThreads?

With this setting the maximum number of threads increases significantly (~ 23k threads on my machine).


Another mainframe approach: I have built experimentally an FBP asynchronous, preemptive implementation, for the IBM mainframe MVS environment, using MVS multitasking. This would allow a SQL call or a Sort to only affect one thread, so it looks very appealing, although the overhead is greater than that of the cooperative implementations. However, it should also make much better use of multiprocessor machines. However, StanWilliams has pointed out that this strategy will only work when the number of tasks is small - when it becomes larger, we may have to assign tasks to threads dynamically, or even share FBP threads between the infrastructure threads. No experimenting has been done with the preliminary MVS version so far, but I would be happy to make it available to anyone who wants to take a stab at it.

One last (MVS) option - maybe far in the future - would be to use the IBM LE/MVS thread capability, but I believe IBM has only enabled it for the POSIX environment, which AFAIK is only invokable from C.

Ruby: Ruby uses "green threads", local to one interpreter - thanks, JohnCowan! This is essentially the same technique that we used in the first three IBM implementations (that I have called "synchronous" above) - their advantages and disadvantages are described quite well in http://www.jguru.com/faq/view.jsp?EID=143462. But for another view, see http://www.cincomsmalltalk.com/blog/blogView?showComments=true&entry=3303013147.

For a discussion of this issue in Erlang, see http://www.erlang.se/publications/xjobb/0089-hedqvist.pdf.

Python:

Extract from http://www.linuxjournal.com/node/7871/print

There's an inherent complexity in asynchronous programming, especially when you need to do many blocking operations in succession. In Python, however, the benefits of threading are diminished by Python's Global Interpreter Lock (GIL). Threaded programming in Python is refreshingly simple, because all internal Python operations are thread-safe. To add an item to a list or set a dictionary key, no locks are required, so as to avoid race conditions among threads. Unfortunately, this is implemented through an interpreter-wide lock that Python's interpreter uses liberally. So, although two threads safely can append to the same list at the same time, if they're appending to two different lists, the same lock is used. Because threaded Python applications suffer a resulting performance hit, asynchronous single-thread programming is all the more desirable for a language such as Python.

See also the Python documentation at http://docs.python.org/api/threads.html.


FlowBasedProgramming | RecentChanges | Preferences
This page is read-only - contact owner for a password | View other revisions
Last edited April 2, 2009 1:48 pm by PaulMorrison (diff)
Search: