<!--
  - Authors:
  -   Denys Duchier     <duchier@ps.uni-sb.de>
  -
  - Copyright:
  -   Denys Duchier, 1998
  -
  - Last change:
  -   $Date: 1999/01/21 09:52:34 $ by $Author: schulte $
  -   $Revision: 1.4 $
  -
  - This file is part of Mozart, an implementation
  - of Oz 3
  -    http://www.mozart-oz.org
  -
  - See the file "LICENSE" or
  -    http://www.mozart-oz.org/LICENSE.html
  - for information on usage and redistribution
  - of this file, and for a DISCLAIMER OF ALL
  - WARRANTIES.
  -
  -->

<chapter id=chapter.concurrency.cheap>
  <title>Concurrency For Free</title>
  <p>This part of the tutorial addresses the following theme: what
happens to programming when support for concurrency is
extremely cheap, economical, and efficient.  Suddenly, an entirely
different style of programming and design is made possible.  We are
going to explore and exploit this new freedom.</p>
  <p>Oz has very efficient, very economical, very lightweight threads,
with fair preemptive scheduling.  We don't mean that Oz threads are
just somewhat better than brand X; we mean that brand X can't even see
our dust with a telescope, er&etc; well, just about anyway!  In order
to assuage the skeptics, we first exhibit a program that demonstrates
massive concurrency and exercises the worst case.  Doubters are
encouraged to throw that program at their favorite programming
language&etc; and watch it die, eventually.  Meanwhile, you could
mount a clay tablet device, and engage in the more rewarding exercise
of installing Windows from sumerian backup.</p>
  <p>The program is invoked with:
<code display proglang=sh/death --threads ?{N} --times ?{M}/
and creates ?{N} threads. Each thread does nothing but <em/yield/
immediately. Normally we would let the preemptive scheduler take care of
interrupting a thread to switch to a new one, but here, in order to
exercise the worst case, as soon as a thread is allowed to run,
it explicitly <em/yields/.  Thus the program does little else but
switch between threads. Each thread yields ?{M} times and then
terminates.   When all threads have terminated, the program also
terminates.</p>
  <p>I just tried the following:
<code display proglang=sh/death --threads 10000 --times 10/
In other words, 10000 threads are created and must each yield 10
times.  This results in 100000 thread switches.  It takes 3s on
this little steam-driven laptop.  I have run the same program on a
real computer at the lab but using:
<code display proglang=sh/death --threads 100000 --times 10/
It takes 7.5s.  There are 100000 threads at all time runnable, and they
must perform 1000000 thread switches.  Try creating 100000 threads in
Java&etc; really, go ahead, I insist! I promise not to laugh!</p>
  <p>Just so you don't have to take my word for it, I coded the same
program in Java and tried:
<code display proglang=sh/java Death 1000 10/
This takes 2:40mn!</p>
  <p>What was the point of this exercise?  It was not prove that Oz is
better than Java; in this respect the test above was deliberately
unfair: Java was never intended to support designs with massive
concurrency&etc; and <em/that/ is the point.  Oz was from the start
designed as a platform for concurrent computation.  That concurrency
is so cheap and efficient makes entirely new designs possible that
would not be realistic or even conceivable in other languages.
Whenever you need to perform an operation asynchronously you simply
spawn a new thread.  You can design your application as a collection
of concurrent objects or agents, etc&etc;</p>
  <section class=unnumbered id=death.in.oz>
    <title/Death by Concurrency in Oz/
<p>Here is the code of the Oz application used in the benchmark above:
<code.extern display to="death.oz"></p>
  </section>
  <section class=unnumbered>
    <title/Death by Concurrency in Java/
    <p>Here is a very similar program, in Java:
<code.extern display to="Death.java" proglang=java></p>
  </section>
</chapter>

<!--
Local Variables:
mode: sgml
mode: auto-fill
sgml-default-dtd-file: "chapter.ced"
sgml-auto-activate-dtd: t
adaptive-fill-mode: nil
End:
-->
