<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Daniel C. Wang's Blog</title><subtitle type="html" /><id>http://blogs.msdn.com/daniwang/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/daniwang/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/daniwang/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2008-11-16T06:08:00Z</updated><entry><title>CCR and C# Iterators</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/daniwang/archive/2009/01/03/ccr-and-c-iterators.aspx" /><id>http://blogs.msdn.com/daniwang/archive/2009/01/03/ccr-and-c-iterators.aspx</id><published>2009-01-03T22:50:00Z</published><updated>2009-01-03T22:50:00Z</updated><content type="html">&lt;P class=CommonTitle minmax_bound="true"&gt;In the comments in my last post grauenwolf pointed out there is a similar use of iterators in the CCR.&amp;nbsp;I found this MSDN example as well &lt;A href="http://msdn.microsoft.com/en-us/library/bb648753.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb648753.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb648753.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I'm not clear how you spawn new threads, but the basic idea is the the same.&amp;nbsp; I'll see if I can write the benchmark using CCR, next time I have a chunck of time free for this sort of stuff.&lt;/P&gt;
&lt;P&gt;Updated: Post discussing the CCR and Erlang &lt;A href="http://www.infoq.com/news/2008/12/CCR"&gt;http://www.infoq.com/news/2008/12/CCR&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9270593" width="1" height="1"&gt;</content><author><name>daniwang</name><uri>http://blogs.msdn.com/members/daniwang.aspx</uri></author></entry><entry><title>Lightweight threading using C# Iterators</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/daniwang/archive/2008/12/29/lightweight-threading-using-c-iterators.aspx" /><id>http://blogs.msdn.com/daniwang/archive/2008/12/29/lightweight-threading-using-c-iterators.aspx</id><published>2008-12-29T05:59:14Z</published><updated>2008-12-29T05:59:14Z</updated><content type="html">&lt;p&gt;Inspired by a few recent posts I’ve run across (&lt;a title="http://msdn.microsoft.com/en-us/magazine/cc546608.aspx" href="http://msdn.microsoft.com/en-us/magazine/cc546608.aspx"&gt;http://msdn.microsoft.com/en-us/magazine/cc546608.aspx&lt;/a&gt; and &lt;a title="http://lambda-the-ultimate.org/node/3131" href="http://lambda-the-ultimate.org/node/3131"&gt;http://lambda-the-ultimate.org/node/3131&lt;/a&gt;). I decided to write a simple threading library&amp;#160; so, I can run the &lt;a title="http://muharem.wordpress.com/2007/07/31/erlang-vs-stackless-python-a-first-benchmark/" href="http://muharem.wordpress.com/2007/07/31/erlang-vs-stackless-python-a-first-benchmark/"&gt;Erlang ring benchmark&lt;/a&gt; in C#. &lt;/p&gt;  &lt;h2&gt;Ring Benchmark (C# Version)&lt;/h2&gt;  &lt;p&gt;Here is the code of the ring benchmark itself, it uses my own ThreadIterators library which I’ll get around to posting one day once I clean it up a bit. &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; ThreadIterators;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RingBenchmark&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Event&amp;gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;       ForwardMessage(Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; inbox,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;                      Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; outbox) {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (; ; ) &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            var evt = inbox.Recv();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; evt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            outbox.Send(evt.Value);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;       SpawnForwaders(&lt;span class="kwrd"&gt;int&lt;/span&gt; n, Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; inbox)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        var prev = inbox;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        var next = inbox;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            next = &lt;span class="kwrd"&gt;new&lt;/span&gt; Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            var thIter = ForwardMessage(prev, next);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;            ThreadIterator.Spawn(thIter);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            prev = next;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; next;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Event&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;        PumpRing(&lt;span class="kwrd"&gt;int&lt;/span&gt; m, Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; outbox)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m; i++)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            outbox.Send(i);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;        outbox.Send(-1);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Event&amp;gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        DrainRing(Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; inbox)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (; ; )&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;            var evt = inbox.Recv();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;            &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; evt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (evt.Value &amp;lt; 0)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;                &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Event&amp;gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;        RingBenchMark(&lt;span class="kwrd"&gt;int&lt;/span&gt; n, &lt;span class="kwrd"&gt;int&lt;/span&gt; m)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;        var inbox = &lt;span class="kwrd"&gt;new&lt;/span&gt; Mailbox&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;        var outbox = SpawnForwaders(n, inbox);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;        var thIter1 = PumpRing(m, inbox)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;        var thIter2 = DrainRing(outbox)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;        ThreadIterator.Spawn(thIter1);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;        var th = ThreadIterator.Spawn(thIter2);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;        &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; th.ExitedEvent;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The Mailbox&amp;lt;T&amp;gt; type is from my library that’s a communication channel with unbounded buffering. This makes Send a non-blocking operation. Potentially, blocking operations like Recv return events which are yielded to inner loop of the threading libraries scheduler. The representation of a thread in my library is simply and enumeration of events, which is just a potentially infinite list of blocking operations, when ever a thread may block, it needs to yield an event which can be used to wake the thread up when the blocking operation completes. &lt;/p&gt;

&lt;h2&gt;Benchmark Results&lt;/h2&gt;

&lt;p&gt;The scheduler itself is a thread safe library, with a single method to pull off&amp;#160; any ready thread from the queue and process it. I call this execution method in a single threaded fashion, but since it is thread safe I can spawn two managed threads to call this scheduling method concurrently. So I can get coroutines or preemptive concurrency. I happen to have an Intel Core 2 Duo running at 2.0 Ghz with 2 GB running 32-bit Vista. So I have data for both cases. I’m comparing it to the Erlang ring benchmark from the link above using the lasted Erlang distribution for Windows.&lt;/p&gt;

&lt;p&gt;Here is a table with the raw data, where I’ve fixed M to 1000 and exponentially increased N.&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="0" border="0"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td width="71"&gt;N, M=1000&lt;/td&gt;

      &lt;td width="77"&gt;Erlang (ms)&lt;/td&gt;

      &lt;td width="122"&gt;C# 2 Threads (ms)&lt;/td&gt;

      &lt;td width="142"&gt;C# Single Threaded&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;64&lt;/td&gt;

      &lt;td width="77"&gt;31&lt;/td&gt;

      &lt;td width="122"&gt;33&lt;/td&gt;

      &lt;td width="142"&gt;42&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;128&lt;/td&gt;

      &lt;td width="77"&gt;31&lt;/td&gt;

      &lt;td width="122"&gt;66&lt;/td&gt;

      &lt;td width="142"&gt;84&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;256&lt;/td&gt;

      &lt;td width="77"&gt;94&lt;/td&gt;

      &lt;td width="122"&gt;174&lt;/td&gt;

      &lt;td width="142"&gt;170&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;512&lt;/td&gt;

      &lt;td width="77"&gt;156&lt;/td&gt;

      &lt;td width="122"&gt;258&lt;/td&gt;

      &lt;td width="142"&gt;336&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;1024&lt;/td&gt;

      &lt;td width="77"&gt;358&lt;/td&gt;

      &lt;td width="122"&gt;513&lt;/td&gt;

      &lt;td width="142"&gt;670&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;2048&lt;/td&gt;

      &lt;td width="77"&gt;624&lt;/td&gt;

      &lt;td width="122"&gt;1038&lt;/td&gt;

      &lt;td width="142"&gt;1354&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;4096&lt;/td&gt;

      &lt;td width="77"&gt;1404&lt;/td&gt;

      &lt;td width="122"&gt;2086&lt;/td&gt;

      &lt;td width="142"&gt;2724&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;8192&lt;/td&gt;

      &lt;td width="77"&gt;2808&lt;/td&gt;

      &lt;td width="122"&gt;4171&lt;/td&gt;

      &lt;td width="142"&gt;5587&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;16384&lt;/td&gt;

      &lt;td width="77"&gt;5351&lt;/td&gt;

      &lt;td width="122"&gt;8307&lt;/td&gt;

      &lt;td width="142"&gt;11288&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;32768&lt;/td&gt;

      &lt;td width="77"&gt;10437&lt;/td&gt;

      &lt;td width="122"&gt;17657&lt;/td&gt;

      &lt;td width="142"&gt;24160&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;65536&lt;/td&gt;

      &lt;td width="77"&gt;20810&lt;/td&gt;

      &lt;td width="122"&gt;33920&lt;/td&gt;

      &lt;td width="142"&gt;63662&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;131072&lt;/td&gt;

      &lt;td width="77"&gt;41042&lt;/td&gt;

      &lt;td width="122"&gt;83268&lt;/td&gt;

      &lt;td width="142"&gt;136578&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;262144&lt;/td&gt;

      &lt;td width="77"&gt;80133&lt;/td&gt;

      &lt;td width="122"&gt;174877&lt;/td&gt;

      &lt;td width="142"&gt;446013&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;




&lt;p&gt;Here’s a graph for that compares the ratio of runtimes.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/daniwang/WindowsLiveWriter/LightweightthreadingusingCIterators_F977/image_2.png" target="_blank"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="217" alt="image" src="http://blogs.msdn.com/blogfiles/daniwang/WindowsLiveWriter/LightweightthreadingusingCIterators_F977/image_thumb.png" width="360" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;First you’ll notice that Erlang is roughly a factor of 2 faster than my version using 2 threads and about 5 times faster for my single threaded version. The version using 2 threads is for the most part faster then the single thread version. The 2 threaded version varies between 3% slower and 100% faster than the single threaded one. I suspect I could do a few things to make my scheduler a bit smarter about utilizing available CPU cores, mainly by taking fewer locks on the work queue.&lt;/p&gt;

&lt;p&gt;The other thing to keep in mind is that these results are for up to 262,144 lightweight threads. There would be no way to have this many C#&amp;#160; managed threads, with a default stack size of 1MB.&amp;#160; (Perhaps, I’ll post a ring benchmark using normal C# threads later.) What’s not shown on this graph is memory footprint. Surprisingly the CLRs footprint was smaller than Erlang, but it’s hard to compare because of GC issues. C# code scaled up pretty well in comparison to Erlang, which to me is not to surprising, assuming you have the right representation of thread control state.&lt;/p&gt;

&lt;h1&gt;Conclusions&lt;/h1&gt;

&lt;p&gt;C# iterators are a quite powerful construct that lets you implement your own lightweight threading abstraction. My library is pure C# and doesn’t use any native code to do this. The only other threading approaches I know about that work at this level, require call-with-current-continuation or monads.&amp;#160; The library is efficient enough that C# can scale as well as Erlang which has a highly specialized and optimized runtime for this scenario. I think there is some room for improvement in my library, so I would not be surprised if I could make the factor of two go away to 10 – 20%. I suspect the GC maybe the final bottleneck though. I think the big take way here is that you don’t need a specialized&amp;#160; language and highly customized runtime to get a highly scalable thread abstraction that is also relatively easy to program.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9255289" width="1" height="1"&gt;</content><author><name>daniwang</name><uri>http://blogs.msdn.com/members/daniwang.aspx</uri></author></entry><entry><title>Windows Azure</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/daniwang/archive/2008/11/16/windows-azure.aspx" /><id>http://blogs.msdn.com/daniwang/archive/2008/11/16/windows-azure.aspx</id><published>2008-11-16T09:08:00Z</published><updated>2008-11-16T09:08:00Z</updated><content type="html">&lt;P&gt;Been a while, since I've updated my blog. I've been working as a developer on the Windows Azure for the last year or so. Now that we've annouced it at PDC, I can talk a bit more on what I've been working on, as well as the challenges in programming the cloud. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9102643" width="1" height="1"&gt;</content><author><name>daniwang</name><uri>http://blogs.msdn.com/members/daniwang.aspx</uri></author></entry></feed>