"I have a mind like a steel... uh... thingy." Patrick Logan's weblog.

Search This Blog

Sunday, May 18, 2008

Toward Finer Tuning of Definitions of Processes and Languages, Reliably

Here's an attempt to define terms more finely (finally?) after reading the latest (final?) response from Ted Neward to Steve Vinoski's attempts at helping Ted to clarify differences between Erlang and other languages and run-times, esp. those based on Java/JVM-ish. At a superficial level of understanding what Ted writes has some meaning. Just enough to be troublesome. So here's my pass at making clarifications.

The first terms to narrow in on are "process" and "thread" as they are used in various languages and operating systems. There are similarities for sure, but the subtle differences are the important aspects when making comparisons. Ted writes a few things using these terms...

Processes in *nix are just as vulnerable to bad coding practices as are processes in Windows or Mac OS X
Aside: Mac OS X _is_ Unix. But that's for a different debate on the merits of Windows per se.

Anyway. I don't expect anyone to argue with Ted on this point, so let's dig deeper into "bad coding practices" and processes. Erlang is a "mostly-functional" language and there is very little shared memory in its concurrency model. This removes many opportunities for bad coding. So can we say that programming an operating system process in Erlang is less vulnerable than programming an operating system process using most popular languages? I would say yes, generally.

the robustness and reliability of a system is entirely held hostage to the skill and care of the worst programmer on the system
The emphasis is Ted's, not mine. There are many fine points to be made about this claim. One is the term "entirely" and another is the term "system". But first is the observation that this claim is about development practices more than anything else. To argue about language and mechanism shouldn't we assume that the teams are skilled at least in their own languages and mechanisms?

Let's say no and look deeper. You won't read much Erlang literature before you come across terms like robustness and reliability, and explanation of language constructs and framework mechanisms that support these traits.

On the other hand one can program in Java and similar languages for years before realizing that attention to robustness and reliability are even the developer's concern.

Back to "system" and "entirely" being at the mercy of the worst programmer. Perhaps the most important point made by the Erlang experts is to expect the worst and to design your system to recover from that. The Erlang culture does its best to help you isolate bad parts and the Erlang mechanisms make that isolation and recovery easier than with most other systems.

Erlang's model is similar to the CLR's AppDomain construct, which has been around since .NET 1.0, and Java's proposed "Isolate" feature which has yet to be implemented.
I'm not going to presume to know anything more about AppDomains than Ted know's about about Erlang, but this comparison seems true only barely. Here's some information I found about AppDomains...
The main purpose of an Application Domain is to isolate our applications from other applications. Application domains run on a single Win32 process... Objects in the same Application Domain communicate directly while Objects that exists in different Application Domains interact with each other by transporting copies of objects to each other or by using proxies for message exchange (by reference).
Any somewhat-skilled programmer familiar in the least with Erlang should be able to tell you significant differences between the AppDomain described above and Erlang's process model. I'm bothered that Ted Neward has such a large stage for making superficial statements that these mechanisms are in any way meaningfully the same. This is a significant disservice to programmers following his writing, trying to learn useful information. If Ted does not have (apparently) even a few days worth of reasonable Erlang experience or even reading, why should he presume to make such significant and horribly misleading statements to his large audience?

Here are the significant differences between these two mechanisms (Erlang processes and dotnet AppDomains)...

  • AppDomains appear to be used to put distinct applications inside the same Windows OS process.
  • Erlang processes are used to decompose a single application into many, small, independent, shared nothing processes.
  • Objects in different AppDomains are considered separate and rarely-interacting.
  • Processes in Erlang are roughly the same "size" as an instance of a major role-playing object in a single application. They collaborate with other processes frequently and are highly interactive.
  • Objects in an AppDomain are "shared-everything", running concurrent, shared-everything threads.
  • Erlang processes (the equivalent of objects in dotnet) in an application are "shared-nothing".
  • AppDomains pass copies of values or references to objects (as far as I can tell from this one article).
  • Erlang processes always pass copies of values. Erlang and its frameworks per se do not provide references, and so it's "shared-nothing" all the way down. The equivalent of "reference to an object" in Erlang is "identifier of a process".
  • AppDomains appear to be a large-grain, compile-time, declarative mechanism. Any Windows OS process would have just a few AppDomains. I would suppose these number in the dozens per OS process.
  • Erlang processes are a fine-grain, run-time, dynamic mechanism. An Erlang node (essentially an OS process) would have many hundreds of processes or more.
Ted continues...
if the argument here is that Erlang's reliability comes from its lack of shared state between threads, hell, man, that's hardly a difficult architecture to cook up. Most transactional systems get there pretty easily, including EJB, though then programmers then go through dozens of hoops to try and break it.
Ted does a pretty good job of hinting that EJB is a broken model. EJB isolation is more like an AppDomain. EJB separates one application from another, with fairly laborious mechanisms required to get them to communicate with each other.

Within an EJB application there is supposed to be no concurrency at all. And so again this is the opposite of Erlang. Erlang encourages high concurrency and ease of interaction. But these points are apparently lost on Ted. Usually one cannot read a single page of Erlang literature without having this made absolutely obvious.

The next post will get into Ted's arguments about language and common run-times.


Barry Kelly said...

I agree that it's pretty clear Ted isn't making a whole lot of sense even to someone with only surface knowledge of Erlang, like myself.

I've written up my own comments on the debate on my own blog. However, a few comments about AppDomains:

* They are indeed share-nothing, in that the communication model for most types is copying and for MarshalByReference-descended types it's fairly transparent proxying.

* AppDomains aren't compile-time or declarative. You create an AppDomain programmatically and load up an assembly (~= jar), find a class inside the domain, and instantiate it - and you normally interact with that class through a proxy. AppDomains aren't a good base for building actors out of, as the CLR tries to keep the two very separate, although there are a couple of holes (Type objects from system libraries, in particular, are shared, and will cause problems if you 'lock' them using the CLR's monitor support.) Consequently, you'd have an awkward time trying to efficiently send messages between them, and they would be quite a bit more heavy-weight, as actual concurrency would require each AppDomain to have at least one Thread created inside it, which would be a real live native thread, rather than a lightweight user-scheduled one.

Matthias said...

I won't take any sides in this conversation. Just -if you want to learn more about AppDomains- MSFT's Chris Brumme had the most fascinating blog about CLR implementation: http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx

The other posts are worth reading, too.

What I particularly took from it is the great lengths the CLR goes to make sure it can reliably terminate an AppDomain and claim all its memory and threads - much more comforting than runaway Java threads in a J2EE container.

In 2003: "Towards the end of V1 ... we were able to squeeze 1000 very simple applications / AppDomains into a single worker process." "Presumably that process would have had 50-100 threads active in it" - i.e. no actor model.

With 64 bit address space I guess the boundaries are different.

Beware, this stuff is from 2003, but the concepts still hold, I guess.


Nat Pryce said...

Your description of EJB is incorrect.

JavaEE is just a framework for writing components that take part in XA distributed transactions. The framework manages the concurrency and transaction lifecycle, and the components just implement the logic that runs within a transaction.

EJB components are reactive objects -- e.g. typical objects as implemented in OO languages like Java or Smalltalk. Their method activations are short-lived and just update the persistent state of the distributed transaction, which is committed at the end of the transaction. The framework manages concurrency by creating objects per thread. The persistent state is the synchronisation point between the threads, but threads are usually isolated because they are working in different transactions.

An application is made up of many components (EJBs, MDBs, persistent entities, etc.). So EJB applications are concurrent. Each component is not.

Blog Archive

About Me

Portland, Oregon, United States
I'm usually writing from my favorite location on the planet, the pacific northwest of the u.s. I write for myself only and unless otherwise specified my posts here should not be taken as representing an official position of my employer. Contact me at my gee mail account, username patrickdlogan.