

Real-World Concurrency (2008) - benwen
http://queue.acm.org/detail.cfm?id=1454462

======
discreteevent
This is the key paragraph:

"When problems resist parallelization or have no appreciable latency to hide,
the third way that concurrent execution can improve performance is to increase
the throughput of the system. Instead of using parallel logic to make a single
operation faster, one can employ multiple concurrent executions of sequential
logic to accommodate more simultaneous work. Importantly, a system using
concurrency to increase throughput need not consist exclusively (or even
largely) of multithreaded code. Rather, those components of the system that
share no state can be left entirely sequential, with the system executing
multiple instances of these components concurrently. The sharing in the system
can then be offloaded to components explicitly designed around parallel
execution on shared state, which can ideally be reduced to those elements
already known to operate well in concurrent environments: the database and/or
the operating system."

Even if you can't use the database or os and still want to get "multiple
concurrent executions of sequential logic" then just use a message queue.
That's what Go provides, what blocking queues in java provide, what most actor
based systems provide (e.g. Akka, Dart), what unix pipes provide and what all
kinds of inter process messaging systems provide. Most of your code can as
impure, sequential and lock free as it always was. You only have to make your
messages immutable.

~~~
kaoD
And that's why I love Node.js: the single-threaded concurrency (or should I
say non-concurrency?) is built-in in the execution model. Building your
architecture decoupled from the ground up is useful, and Node.js does a great
job at it.

I found Redis is an awesome middleware for MQ purposes. Its builtin PubSub
system, blocking POPs and amazing speed make it a perfect fit.

But beware: it's easy to get it wrong and make the system a tangled mess of
messages. Just make sure the message dispatch overhead is worth it.

~~~
fforw
Is node actually able to use more than one core now?

~~~
DonPellegrino
It has been able to for a while! Check out the cluster module, processes
listening to the same port are load balanced and communication between
processes is obviously (since each process only has 1 thread due to the event
loop) done by message passing.

------
miga
I would rather recommend chapter on deterministic concurrency in this paper:
<http://community.haskell.org/~simonmar/par-tutorial.pdf> [In particular `par`
and promises.]

This solution is quickest to debug, and most efficient. One can also use
multiprocessing-like approach:
<http://docs.python.org/2/library/multiprocessing.html>

My last 15 years of practice indicate that other approaches lead to
unnecessary complication, and are less likely to be effective (threads and
semaphores in particular.)

~~~
JoeAltmaier
That!

Message passing is a reasonable approach. Its particularly simple to design,
and deadlock-free if message processors don't block on further messages.

Drawbacks: Simplest when each message class (or queue) has one thread to
handle it. But that doesn't optimize for available hyperthreads.

~~~
pron
Message passing is often insufficient without a centralized concurrent data
structure (a database can serve that purpose). That is why Erlang has ETS (but
that only guarantees isolation for single entity transactions), and Akka and
Clojure have STM (and the Java concurrent data structures).

~~~
swah
Is there something preventing people from writing correct, multi-threaded apps
in Clojure (and kicking Python/Rubys asses)?

~~~
FreezerburnV
Clojure actually has a lot of stuff in its design specifically for
multithreading. Like the GP post said, Clojuer has Software Transactional
Memory (STM) on top of immutable data structures to make messing up
multithreaded programs hard, and you'd almost have to deliberately do so.

And yes, like another reply says, Clojure (and pretty much anything that's
designed well and runs on the JVM) is much, much faster than Python/Ruby by
default. A lot of this has to do with the JIT compiler that Java has been
working on for a long time, which Python/Ruby don't have outside of an PyPy
implementation. Also Python/Ruby don't have access to actual threads by
default, because it has a global lock. They run everything basically in a
single thread.

~~~
swah
That is exactly my question. If Clojure has got great performance and great
multithraeding support, why haven't it gained a greater share of the dynamic
languages market?

------
benwen
"This article is half stern lecture on the merits of abstinence and half Kama
Sutra."

