<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Oren Ellenbogen's Blog</title>
    <link>http://www.lnbogen.com/</link>
    <description>Striving for agile development</description>
    <language>en-us</language>
    <copyright>Oren Ellenbogen</copyright>
    <lastBuildDate>Fri, 07 Nov 2008 15:40:02 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.2.8279.16125</generator>
    <managingEditor>oren.ellenbogen@gmail.com</managingEditor>
    <webMaster>oren.ellenbogen@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=36259054-72d3-4f37-8a93-a1e55f3e872e</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,36259054-72d3-4f37-8a93-a1e55f3e872e.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,36259054-72d3-4f37-8a93-a1e55f3e872e.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=36259054-72d3-4f37-8a93-a1e55f3e872e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
"Why do you love working as X so much? so much that you're willing to spend that many
hours of your life at?"
</p>
        <p>
Pause for a second. Try to close your eyes and think what will be your answer for
this question?
</p>
        <p>
          <br />
For me, the answer is obvious: It's the people and challenges that make my brain tick
and my motivation SKY high. It's the feeling that <strong>I</strong> can <em>really</em> make
things better by investing everything I got into it that makes me proud of my work.
I get huge satisfaction installing TFS 2008, trying to make our Integration Tests
work X6 faster, practicing some Agile principles I've read about or take any other
"dirty yet important work" no one would like to touch. I'm not scared of  hard
work and if I can feel, down there in my stomach, that it would make my teammates
more productive - I'll do anything I can to make it happen. Oh, and I'm trying to
build one of the most complex <a href="http://www.delver.com/">search engine</a> the
world has the offer with a bunch of <a href="http://ripper234.com/">b</a>-<a href="http://pashabitz.com/">r</a>-<a href="http://blog.karmona.com/">i</a>-<a href="http://www.tomergabel.com/">l</a>-<a href="http://blog.shlomoid.com/">l</a>-<a href="http://www.kenegozi.com/blog/">i</a>-<a href="http://omriqa.blogspot.com/">a</a>-<a href="http://blog.agmon.com/">n</a>-<a href="http://blog.delver.com/">t</a> guys!
Can you blame me for working so hard, enjoying <em>every</em> minute of it?
</p>
        <p>
Sure, getting a few bucks more would be great, but that will <em>not</em> make me <strong>proud</strong> of
what I'm doing. One of the main things I've learned in my 8 years of developing software,
is that highly motivated teams will always make the best products. Leave aside for
a moment the productivity boost these teams enjoy and imagine their daily work, their
lunches together, their working environment, their joy of talking with one another
about day to day stuff. Imagine how they dream about their goals together, discussing
ways to making it better and more enjoyable. It's the buzz these companies have that
drove the best guys to them, so "effortlessly". The commitment to one another will
make sure you'll build quality systems, that you'll try your best to deliver on time,
to make it better, smarter, BIGGER, <em>every</em><em>single day</em>. It will allow
you to grow like you could never anticipated. Trying to grow this culture in your
team is one of the hardest things in the world, way harder than <em>any</em> logical
puzzle thrown at you. Believe me.
</p>
        <p>
          <strong>It's just so damn hard to get it right.</strong>
        </p>
        <strong>
          <p>
            <br />
"
</p>
        </strong>There are many men who feel a kind of twister pride in cynicism<strong>"</strong> (Theodore
Roosevelt, <a href="http://www.theodore-roosevelt.com/trsorbonnespeech.html">The Man
In The Arena</a> speech).<br />
Over cynicism means death for any joint effort. No matter how strong your team is,
negativity and cynicism will break your team spirit. It always does. 
<br />
Stop being so negative, so cynical about your actions and your dreams. You can do
great things by answer the question above and remember that it's all about the people
around you. It's all about you! you can actually make everyone around you better by
taking action. Stop listening to people who thinks they know best and mocking you
with "you're only a tiny nail in a giant machine". Don't be afraid of constantly trying
to make a difference, even if you'll lose here and there. Read books, talk about them
and your ideas, share and try, try, try, and try again! 
<p>
This attitude will probably make you a winner, someone that others will enjoy working
with, being with, taking inspiration from. 
<br />
I know that these guys are the one <strong>I</strong> love working with or going to
a bar close by, drinking some beer and talking about how to change the world.<br /><br />
Best people simply do for each other.
</p><img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=36259054-72d3-4f37-8a93-a1e55f3e872e" /></body>
      <title>Best teams work for each other</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,36259054-72d3-4f37-8a93-a1e55f3e872e.aspx</guid>
      <link>http://www.lnbogen.com/2008/11/07/BestTeamsWorkForEachOther.aspx</link>
      <pubDate>Fri, 07 Nov 2008 15:40:02 GMT</pubDate>
      <description>&lt;p&gt;
"Why do you love working as X so much? so much that you're willing to spend that many
hours of your life at?"
&lt;/p&gt;
&lt;p&gt;
Pause for a second. Try to close your eyes and think what will be your answer for
this question?
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
For me, the answer is obvious: It's the people and challenges that make my brain tick
and my motivation SKY high. It's the feeling that &lt;strong&gt;I&lt;/strong&gt; can &lt;em&gt;really&lt;/em&gt; make
things better by investing everything I got into it that makes me proud of my work.
I get huge satisfaction installing TFS 2008, trying to make our Integration Tests
work X6 faster, practicing some Agile principles I've read about or take any other
"dirty yet important work" no one would like to touch. I'm not scared of&amp;nbsp; hard
work and if I can feel, down there in my stomach, that it would make my teammates
more productive - I'll do anything I can to make it happen. Oh, and I'm trying to
build one of the most complex &lt;a href="http://www.delver.com/"&gt;search engine&lt;/a&gt; the
world has the offer with a bunch of &lt;a href="http://ripper234.com/"&gt;b&lt;/a&gt;-&lt;a href="http://pashabitz.com/"&gt;r&lt;/a&gt;-&lt;a href="http://blog.karmona.com/"&gt;i&lt;/a&gt;-&lt;a href="http://www.tomergabel.com/"&gt;l&lt;/a&gt;-&lt;a href="http://blog.shlomoid.com/"&gt;l&lt;/a&gt;-&lt;a href="http://www.kenegozi.com/blog/"&gt;i&lt;/a&gt;-&lt;a href="http://omriqa.blogspot.com/"&gt;a&lt;/a&gt;-&lt;a href="http://blog.agmon.com/"&gt;n&lt;/a&gt;-&lt;a href="http://blog.delver.com/"&gt;t&lt;/a&gt; guys!
Can you blame me for working so hard, enjoying &lt;em&gt;every&lt;/em&gt; minute of it?
&lt;/p&gt;
&lt;p&gt;
Sure, getting a few bucks more would be great, but that will &lt;em&gt;not&lt;/em&gt; make me &lt;strong&gt;proud&lt;/strong&gt; of
what I'm doing. One of the main things I've learned in my 8 years of developing software,
is that highly motivated teams will always make the best products. Leave aside for
a moment the productivity boost these teams enjoy and imagine their daily work, their
lunches together, their working environment, their joy of talking with one another
about day to day stuff. Imagine how they dream about their goals together, discussing
ways to making it better and more enjoyable. It's the buzz these companies have that
drove the best guys to them, so "effortlessly". The commitment to one another will
make sure you'll build quality systems, that you'll try your best to deliver on time,
to make it better, smarter, BIGGER, &lt;em&gt;every&lt;/em&gt; &lt;em&gt;single day&lt;/em&gt;. It will allow
you to grow like you could never anticipated. Trying to grow this culture in your
team is one of the hardest things in the world, way harder than &lt;em&gt;any&lt;/em&gt; logical
puzzle thrown at you. Believe me.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;It's just so damn hard to get it right.&lt;/strong&gt;
&lt;/p&gt;
&lt;strong&gt; 
&lt;p&gt;
&lt;br&gt;
"
&lt;/strong&gt;There are many men who feel a kind of twister pride in cynicism&lt;strong&gt;"&lt;/strong&gt; (Theodore
Roosevelt, &lt;a href="http://www.theodore-roosevelt.com/trsorbonnespeech.html"&gt;The Man
In The Arena&lt;/a&gt; speech).&lt;br&gt;
Over cynicism means death for any joint effort. No matter how strong your team is,
negativity and cynicism will break your team spirit. It always does. 
&lt;br&gt;
Stop being so negative, so cynical about your actions and your dreams. You can do
great things by answer the question above and remember that it's all about the people
around you. It's all about you! you can actually make everyone around you better by
taking action. Stop listening to people who thinks they know best and mocking you
with "you're only a tiny nail in a giant machine". Don't be afraid of constantly trying
to make a difference, even if you'll lose here and there. Read books, talk about them
and your ideas, share and try, try, try, and try again! &gt;
&lt;p&gt;
This attitude will probably make you a winner, someone that others will enjoy working
with, being with, taking inspiration from. 
&lt;br&gt;
I know that these guys are the one &lt;strong&gt;I&lt;/strong&gt; love working with or going to
a bar close by, drinking some beer and talking about how to change the world.&lt;br&gt;
&lt;br&gt;
Best people simply do for each other.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=36259054-72d3-4f37-8a93-a1e55f3e872e" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,36259054-72d3-4f37-8a93-a1e55f3e872e.aspx</comments>
      <category>Life</category>
      <category>Management</category>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=6ebfb784-0192-44ed-a582-a0aed3e94ec7</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,6ebfb784-0192-44ed-a582-a0aed3e94ec7.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,6ebfb784-0192-44ed-a582-a0aed3e94ec7.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=6ebfb784-0192-44ed-a582-a0aed3e94ec7</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We're doing a lot of thinking these days about which features will give us the best
ROI, trying to prioritize existing features and asking ourselves "did we miss something?
is there a <em>new</em> feature out there we left behind?". It's not easy to think
about great one-of-a-kind ideas. It is easy though to make it almost impossible. 
</p>
        <p>
Why? it's all because the <a href="http://www.journalofvision.org/4/8/522/">"parallel"
right hemisphere of our brain</a>, imagine the following brain storming conversation: 
</p>
        <p>
me(<strong>L</strong>eft brain): Alright I've got one! The user will enter the screen,
do X and Y (we'll do some Z behind the scene) to receive ... 
<br />
   me(<strong>R</strong>ight brain kicks in): but, doing Z will take me
two weeks to develop..<br />
   me(R): gosh, we'll need to build a dictionary and hold it in memory if
we want it to scale..<br />
   me(R): reminder, use ReaderWriteLockSlim this time. It's much faster
than ReaderWriterLock!<br />
   me(R): I guess that this feature is not as important as feature F1, maybe
I'm spending my time thinking about this feature??!<br />
   me(R): I'm so hungry!<br />
   me(R): Oh, we can use [some service name] to do Z. Cool, so now this
feature is feasible.<br />
   me(R): crap, [some service name] cost money, I think.<br /><br />
[To the surrounding, it looks like I'm saying one fluent sentence of course. During
that time they have their right brain working on "why not" / "how" / "when"]<br />
 <br />
   joe(R): gosh, is he for real? this is the lamest idea I've heard!<br />
   jack(R): hmm, maybe he have a point there. This feature reminds me something
I've always wanted to do... what was it now??...<br />
   jack(R): naa.. this guy is crazy. for sure.<br />
   joe(R): oh wait! we can use something I wrote to implement this feature!
might be cool to use this code finally. It is laying there for ages.<br />
   sarah(R): wonderful idea! I wonder if I'll be assigned to work on it?<br />
   jack(R): I'm listening to his bubbling for 20 minutes now. self reminder:
talk about a bonus with the CEO.<br />
   sarah(R): I need coffee! God, if you'll end this meeting now I promise
the donate 10$ for charity! coffee... please...
</p>
        <p>
me(L): .. a brilliant search result !!
</p>
        <p>
          <br />
Any wonder that most brain storming meetings are futile?
</p>
        <p>
          <br />
Brain storming is a process that should be mastered and I suggest that you'll jump
to the nearest browser to find books at the topic, it's a skill worth investing time
at.<br />
Before you do so, here are some rules <em>I use</em> to silent my right brain while
doing Left Brain Storming:
</p>
        <ol>
          <li>
Never ever prioritize your ideas <em>during</em> brain storming. I can't stress enough
how important is this rule. Don't worry about it <em>now</em>, you'll have time later.  
</li>
          <li>
Listen to others. 
</li>
          <li>
Be patient = don't judge quality of ideas. 
</li>
          <li>
Write everything down. I really mean everything! There are no "stupid ideas" now. 
</li>
          <li>
            <em>You</em> are <em>not</em> going to execute these ideas. At least that is what
you should tell your right brain during that time. 
</li>
          <li>
Understand the meaning behind the feature, imagine how it will work, not how it will
be executed! 
</li>
          <li>
Don't invest more than 2 hours in a single brain storming meeting. If you feel you've
missed some ideas, rest a few hours (or even better - a few days) and then give it
another shoot. "Burned out quickly, left brain does. Burned out leads to impatience.
Impatience kicking the right brain in action. Right brain means trouble for your brain
storming meeting" -- so does <a href="http://en.wikipedia.org/wiki/Yoda">Master Yoda</a> say
(well, sort of) 
</li>
          <li>
80/20: after you're done throwing out ideas (or the 2h gong), go over the features
you've raised and mark features you think are interesting and feasible with 80 and
features that are not with 20. This should take no longer than 2 minutes, so please
use only 80 and 20 as numbers. 
</li>
          <li>
Set a separate meeting to prioritize features with the existing backlog you've got.
Important: don't do it at the same day, you'll probably want to sleep things over.</li>
        </ol>
        <p>
          <br />
Happy hunting!
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=6ebfb784-0192-44ed-a582-a0aed3e94ec7" />
      </body>
      <title>Left Brain Storming</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,6ebfb784-0192-44ed-a582-a0aed3e94ec7.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/31/LeftBrainStorming.aspx</link>
      <pubDate>Fri, 31 Oct 2008 13:14:30 GMT</pubDate>
      <description>&lt;p&gt;
We're doing a lot of thinking these days about which features will give us the best
ROI, trying to prioritize existing features and asking ourselves "did we miss something?
is there a &lt;em&gt;new&lt;/em&gt; feature out there we left behind?". It's not easy to think
about great one-of-a-kind ideas. It is easy though to make it almost impossible. 
&lt;/p&gt;
&lt;p&gt;
Why? it's all because the &lt;a href="http://www.journalofvision.org/4/8/522/"&gt;"parallel"
right hemisphere of our brain&lt;/a&gt;, imagine the following brain storming conversation: 
&lt;/p&gt;
&lt;p&gt;
me(&lt;strong&gt;L&lt;/strong&gt;eft brain): Alright I've got one! The user will enter the screen,
do X and Y (we'll do some Z behind the scene) to receive ... 
&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(&lt;strong&gt;R&lt;/strong&gt;ight brain kicks in): but, doing Z will take me
two weeks to develop..&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): gosh, we'll need to build a dictionary and hold it in memory if
we want it to scale..&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): reminder, use ReaderWriteLockSlim this time. It's much faster
than ReaderWriterLock!&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): I guess that this feature is not as important as feature F1, maybe
I'm spending my time thinking about this feature??!&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): I'm so hungry!&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): Oh, we can use [some service name] to do Z. Cool, so now this
feature is feasible.&lt;br&gt;
&amp;nbsp;&amp;nbsp; me(R): crap, [some service name] cost money, I think.&lt;br&gt;
&lt;br&gt;
[To the surrounding, it looks like I'm saying one fluent sentence of course. During
that time they have their right brain working on "why not" / "how" / "when"]&lt;br&gt;
&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp; joe(R): gosh, is he for real? this is the lamest idea I've heard!&lt;br&gt;
&amp;nbsp;&amp;nbsp; jack(R): hmm, maybe he have a point there. This feature reminds me something
I've always wanted to do... what was it now??...&lt;br&gt;
&amp;nbsp;&amp;nbsp; jack(R): naa.. this guy is crazy. for sure.&lt;br&gt;
&amp;nbsp;&amp;nbsp; joe(R): oh wait! we can use something I wrote to implement this feature!
might be cool to use this code finally. It is laying there for ages.&lt;br&gt;
&amp;nbsp;&amp;nbsp; sarah(R): wonderful idea! I wonder if I'll be assigned to work on it?&lt;br&gt;
&amp;nbsp;&amp;nbsp; jack(R): I'm listening to his bubbling for 20 minutes now. self reminder:
talk about a bonus with the CEO.&lt;br&gt;
&amp;nbsp;&amp;nbsp; sarah(R): I need coffee! God, if you'll end this meeting now I promise
the donate 10$ for charity! coffee... please...
&lt;/p&gt;
&lt;p&gt;
me(L): .. a brilliant search result !!
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Any wonder that most brain storming meetings are futile?
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Brain storming is a process that should be mastered and I suggest that you'll jump
to the nearest browser to find books at the topic, it's a skill worth investing time
at.&lt;br&gt;
Before you do so, here are some rules &lt;em&gt;I use&lt;/em&gt; to silent my right brain while
doing Left Brain Storming:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Never ever prioritize your ideas &lt;em&gt;during&lt;/em&gt; brain storming. I can't stress enough
how important is this rule. Don't worry about it &lt;em&gt;now&lt;/em&gt;, you'll have time later.&amp;nbsp; 
&lt;li&gt;
Listen to others. 
&lt;li&gt;
Be patient = don't judge quality of ideas. 
&lt;li&gt;
Write everything down. I really mean everything! There are no "stupid ideas" now. 
&lt;li&gt;
&lt;em&gt;You&lt;/em&gt; are &lt;em&gt;not&lt;/em&gt; going to execute these ideas. At least that is what
you should tell your right brain during that time. 
&lt;li&gt;
Understand the meaning behind the feature, imagine how it will work, not how it will
be executed! 
&lt;li&gt;
Don't invest more than 2 hours in a single brain storming meeting. If you feel you've
missed some ideas, rest a few hours (or even better - a few days) and then give it
another shoot. "Burned out quickly, left brain does. Burned out leads to impatience.
Impatience kicking the right brain in action. Right brain means trouble for your brain
storming meeting" -- so does &lt;a href="http://en.wikipedia.org/wiki/Yoda"&gt;Master Yoda&lt;/a&gt; say
(well, sort of) 
&lt;li&gt;
80/20: after you're done throwing out ideas (or the 2h gong), go over the features
you've raised and mark features you think are interesting and feasible with 80 and
features that are not with 20. This should take no longer than 2 minutes, so please
use only 80 and 20 as numbers. 
&lt;li&gt;
Set a separate meeting to prioritize features with the existing backlog you've got.
Important: don't do it at the same day, you'll probably want to sleep things over.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;br&gt;
Happy hunting!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=6ebfb784-0192-44ed-a582-a0aed3e94ec7" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,6ebfb784-0192-44ed-a582-a0aed3e94ec7.aspx</comments>
      <category>Agile</category>
      <category>Management</category>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=5dd36c56-0901-490b-a137-268871050d92</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,5dd36c56-0901-490b-a137-268871050d92.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,5dd36c56-0901-490b-a137-268871050d92.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=5dd36c56-0901-490b-a137-268871050d92</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
[ <a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
1</a>, <a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
2</a>, this is <a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
3</a> ]<br /><br />
In <a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">part
1</a> I've talked about the general notion behind SpawnEnumerator. In <a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">part
2</a> I've implemented it and talked a bit about CCR and how it works under the hood.<br />
In the third and last part I'll try to show how we can actually execute billions of
tasks very easily.<br /><br /><strong>Iterating over billions of tasks:</strong></p>
        <p>
In my <a href="http://www.lnbogen.com/TheBeautyOfYieldStatement.aspx">previous post</a> I've
tried to show one of the greatest yet unused features in C# 2.0 - the yield statement.
I've closed the post with:<br />
"Prefer using the yield statement as long as calculating values doesn't require <strong>holding</strong> an
expensive resource like a DB connection, or a FileHandler for <strong>long period
of time</strong>."
</p>
        <p>
Now, let's assume that we have 100,000,000 Tasks to pull from a repository (DB, files,
doesn't really matter) and execute them all via SpawnEnumerator. 
<br />
Should we define a list of Task, fill it with 100,000,000 items and then iterate over
it? of course not! we can't even if we want to.<br />
Assuming that reading 1000 (for example) Tasks is <strong>much faster</strong> than
executing them (it usually is), and it's safe to hold them in memory, we can "bulk
read &amp; yield" the entire thing:
</p>
        <blockquote>
          <p>
public delegate T Func&lt;T&gt;();
</p>
        </blockquote>
        <blockquote>
          <p>
public static class Yield<br />
{<br />
    public static IEnumerable&lt;T&gt; Bulked&lt;T&gt;(Func&lt;IEnumerable&lt;T&gt;&gt;
bulkYielder)<br />
    {<br />
        while (true)<br />
        {<br />
            IEnumerable&lt;T&gt;
yielder = bulkYielder();<br />
            if (yielder ==
null)<br />
               
throw new ArgumentException("bulkYielder cannot return a null enumerable", "bulkYielder"); 
</p>
        </blockquote>
        <blockquote>
          <p>
            int itemsGiven
= 0;<br />
            foreach (T t in
yielder)<br />
            {<br />
               
itemsGiven++;<br />
               
yield return t;<br />
            } 
</p>
        </blockquote>
        <blockquote>
          <p>
            if (itemsGiven
== 0)<br />
               
break;<br />
        }<br />
    }<br />
}
</p>
        </blockquote>
        <p>
This can be used to return a stream of "tasks bulk" :
</p>
        <blockquote>
          <p>
Yield.Bulked&lt;Task&gt;(delegate { return tasksRepository.Dequeue(1000); }) // return
the <strong>next</strong> 1000 from the 100,000,000 items queue until no more tasks
exists in the repository.
</p>
        </blockquote>
        <blockquote>
          <p>
            <strong>Important note</strong>: 
<br />
In this scenario, we should return 1000 items from Dequeue method <strong>without</strong> using
yield to avoid holding expensive resources for long period of time (as discussed).<br />
Once we have those 1000 items, we can yield each one of them to the caller (very cheap,
no resources are used).
</p>
        </blockquote>
        <p>
Finally, we can execute billions of tasks in parallel via SpawnEnumerator:
</p>
        <blockquote>
          <p>
IEnumerator&lt;Task&gt; tasksEnumerator = Yield.Bulked&lt;Task&gt;(delegate { return
tasksRepository.Dequeue(1000); });<br />
Action&lt;Task&gt; taskHandler = delegate(Task t) { /* execute single task */ }; 
</p>
        </blockquote>
        <blockquote>
          <p>
// execute the tasks in parallel, using 50 threads and holding ~1000 items in memory.<br />
_tasksExecutor = SpawnEnumerator&lt;Task&gt;.Start(50, "mypool", 1000, tasksEnumerator,
taskHandler); 
</p>
          <p>
// note:don't forget to dispose _tasksExecutor when killing/stopping app!
</p>
        </blockquote>
        <p>
          <br />
Using Yield.Bulked guarantees that we won't hold expensive resources for too long
while allowing us to generate a "stream" of Tasks to run in parallel.<br />
The code is easy to read and follow (I hope) and we gain a simple method for executing
billions of tasks very effectively (CPU &amp; memory wise).
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=5dd36c56-0901-490b-a137-268871050d92" />
      </body>
      <title>Part3: SpawnEnumerator, dealing with billions of independent items</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,5dd36c56-0901-490b-a137-268871050d92.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/18/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx</link>
      <pubDate>Sat, 18 Oct 2008 23:39:07 GMT</pubDate>
      <description>&lt;p&gt;
[ &lt;a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
1&lt;/a&gt;, &lt;a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
2&lt;/a&gt;, this is &lt;a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
3&lt;/a&gt; ]&lt;br&gt;
&lt;br&gt;
In &lt;a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;part
1&lt;/a&gt; I've talked about the general notion behind SpawnEnumerator. In &lt;a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;part
2&lt;/a&gt; I've implemented it and talked a bit about CCR and how it works under the hood.&lt;br&gt;
In the third and last part I'll try to show how we can actually execute billions of
tasks very easily.&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;Iterating over billions of tasks:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
In my &lt;a href="http://www.lnbogen.com/TheBeautyOfYieldStatement.aspx"&gt;previous post&lt;/a&gt; I've
tried to show one of the greatest yet unused features in C# 2.0 - the yield statement.
I've closed the post with:&lt;br&gt;
"Prefer using the yield statement as long as calculating values doesn't require &lt;strong&gt;holding&lt;/strong&gt; an
expensive resource like a DB connection, or a FileHandler for &lt;strong&gt;long period
of time&lt;/strong&gt;."
&lt;/p&gt;
&lt;p&gt;
Now, let's assume that we have 100,000,000 Tasks to pull from a repository (DB, files,
doesn't really matter) and execute them all via SpawnEnumerator. 
&lt;br&gt;
Should we define a list of Task, fill it with 100,000,000 items and then iterate over
it? of course not! we can't even if we want to.&lt;br&gt;
Assuming that reading 1000 (for example) Tasks is &lt;strong&gt;much faster&lt;/strong&gt; than
executing them (it usually is), and it's safe to hold them in memory, we can "bulk
read &amp;amp; yield" the entire thing:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
public delegate T Func&amp;lt;T&amp;gt;();
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
public static class Yield&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerable&amp;lt;T&amp;gt; Bulked&amp;lt;T&amp;gt;(Func&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt;
bulkYielder)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;T&amp;gt;
yielder = bulkYielder();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (yielder ==
null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
throw new ArgumentException("bulkYielder cannot return a null enumerable", "bulkYielder"); 
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int itemsGiven
= 0;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T t in
yielder)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
itemsGiven++;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
yield return t;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } 
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (itemsGiven
== 0)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
break;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This can be used to return a stream of "tasks bulk" :
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Yield.Bulked&amp;lt;Task&amp;gt;(delegate { return tasksRepository.Dequeue(1000); }) // return
the &lt;strong&gt;next&lt;/strong&gt; 1000 from the 100,000,000 items queue until no more tasks
exists in the repository.
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Important note&lt;/strong&gt;: 
&lt;br&gt;
In this scenario, we should return 1000 items from Dequeue method &lt;strong&gt;without&lt;/strong&gt; using
yield to avoid holding expensive resources for long period of time (as discussed).&lt;br&gt;
Once we have those 1000 items, we can yield each one of them to the caller (very cheap,
no resources are used).
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Finally, we can execute billions of tasks in parallel via SpawnEnumerator:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
IEnumerator&amp;lt;Task&amp;gt; tasksEnumerator = Yield.Bulked&amp;lt;Task&amp;gt;(delegate { return
tasksRepository.Dequeue(1000); });&lt;br&gt;
Action&amp;lt;Task&amp;gt; taskHandler = delegate(Task t) { /* execute single task */ }; 
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
// execute the tasks in parallel, using 50 threads and holding ~1000 items in memory.&lt;br&gt;
_tasksExecutor = SpawnEnumerator&amp;lt;Task&amp;gt;.Start(50, "mypool", 1000, tasksEnumerator,
taskHandler); 
&lt;p&gt;
// note:don't forget to dispose _tasksExecutor when killing/stopping app!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;br&gt;
Using Yield.Bulked guarantees that we won't hold expensive resources for too long
while allowing us to generate a "stream" of Tasks to run in parallel.&lt;br&gt;
The code is easy to read and follow (I hope) and we gain a simple method for executing
billions of tasks very effectively (CPU &amp;amp; memory wise).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=5dd36c56-0901-490b-a137-268871050d92" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,5dd36c56-0901-490b-a137-268871050d92.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=bc44ca02-60c1-4593-a0fe-7856625fe0e7</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,bc44ca02-60c1-4593-a0fe-7856625fe0e7.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,bc44ca02-60c1-4593-a0fe-7856625fe0e7.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=bc44ca02-60c1-4593-a0fe-7856625fe0e7</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
How many of you played with <a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx">C#
yield statement</a> ? I guess that most of you did. 
<br />
Anyway, like most of the MSDN examples out there, when used incorrectly, it could
introduce <em>very</em> bad behavior to your code. Consider the following:
</p>
        <p>
public IEnumerable&lt;User&gt; GetUsers(int count)<br />
{<br />
    using (MysqlConnection connection = new MysqlConnection("..."))<br />
    {<br />
        // MysqlDataReader reader = create an MysqlCommand
and execute it<br />
        while (reader.Read())<br />
            yield return new
User(/*... fill parameters from the reader ... */);<br />
    }<br />
} 
</p>
        <p>
Looks pretty harmless right? Not quite. The yield statement is actually transformed
to a "state machine" which means that every time we yield a result back to the client
(the caller of GetUsers in our example), we <strong>wait</strong> for the client to
call to the next item (via IEnumerator&lt;T&gt;.MoveNext()). <strong>The code above
will hold the connection open until the client done iterating all of the User items</strong>.
This will lead into major scalability issues very quickly! You should always keep
your DB connections open for short period to prevent connection exhaustion (threads
waiting for available DB connection in the pool for long period, until timeout). Because
yield returns the control <strong>to the caller</strong>, it might be that the caller
will "take his time" thus leading to connection exhaustion.
</p>
        <p>
          <br />
On the other hand, used wisely and <em>yield</em> yields (lame joke, sorry) <em>HUGE</em> benefits:<br />
[note: code written in notepad, stupidity won't compile]
</p>
        <ul>
          <li>
            <strong>Avoid <em>useless</em> memory allocations</strong>
          </li>
        </ul>
        <blockquote>
          <p>
            <strong>#1:</strong>
            <br />
How many times you end up creating something like this:
</p>
          <p>
    public List&lt;T&gt; Filter(List&lt;T&gt; input, Predicate&lt;T&gt;
predicate)<br />
    {<br />
       List&lt;T&gt; output = new List&lt;T&gt;(input.Count
/2);<br />
       foreach (T item in input)<br />
          if (predicate(item))<br />
             output.Add(item); 
</p>
          <p>
       return output;<br />
   } 
</p>
          <p>
We allocate much more memory than we need only to hold the output during the calculation.
A better approach will be:
</p>
          <p>
    public IEnumerator&lt;T&gt; Filter(IEnumerator&lt;T&gt; input,
Predicate&lt;T&gt; predicate)<br />
    {<br />
       foreach (T item in input)<br />
          if (predicate(item))<br />
             yield return
item;<br />
   }
</p>
          <p>
This way we allocate only <strong>one</strong> T at a time (will be saved in the generated
state machine). In addition, the client could choose to send each item via yield as
well, thus saving the need to create the "input" before calling our Filter method.
</p>
          <p>
            <strong>
              <br />
#2:</strong>
            <br />
Another oh-(gosh-why)-so-common example is the following:
</p>
          <p>
public void Save(T item)<br />
{<br />
    Save(new T[] { item });<br />
} 
</p>
          <p>
public void Save(ICollection&lt;T&gt; items)<br />
{<br />
    // do your magic here to save items<br />
} 
</p>
          <p>
Assuming you call Save with a single item quite a lot, you're allocating <strong>A
LOT</strong> of memory to create one-item arrays. A better approach will be:
</p>
          <p>
public void Save(T item)<br />
{<br />
    Save(Yield.One(item));<br />
} 
</p>
          <p>
public void Save(IEnumerator&lt;T&gt; items)<br />
{<br />
    // do your magic here to save items<br />
} 
</p>
          <p>
public static class Yield<br />
{<br />
    public static IEnumerator&lt;T&gt; One&lt;T&gt;(T item)<br />
    {<br />
        yield item;<br />
    }<br />
} 
</p>
          <p>
~Zero memory allocation here.
</p>
        </blockquote>
        <ul>
          <li>
            <strong>Avoid "impossible" memory allocation</strong>
          </li>
        </ul>
        <blockquote>
          <p>
Let's say you want to read a 20G file with emails where every line holds a single
email. Trying to declare a List&lt;string&gt; and filling it up will make your memory
blow up obviously. You simply can't hold that much in memory. Instead, you can use
Stream.ReadLine and yield back each row to your client, until all of the emails are
taken care of. Yes, you can try to read the file in chunks (keeping a pointer), but
this is exactly what yield does under the hood. Reminder: DRY principle is gold (or
Don't Repeat .Net Framework, in our case).
</p>
        </blockquote>
        <ul>
          <li>
            <strong>Execute synchronous</strong>
            <strong>code asynchronously</strong> (nicely
achieved via <a href="http://msdn.microsoft.com/en-us/magazine/cc163556.aspx">CCR</a>)</li>
        </ul>
        <blockquote>
          <p>
A bit advanced, but you can read all about it <a href="http://msdn.microsoft.com/en-us/library/bb648753.aspx">here</a>.
The great benefit is you can transform (almost) any "yield based" code to run async,
if needed/wanted.
</p>
        </blockquote>
        <p>
          <strong>
            <br />
Recap:<br /></strong>Prefer using the yield statement as long as calculating values doesn't require <strong>holding</strong> an
expensive resource like a DB connection, or a FileHandler for <strong>long period
of time</strong>.
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=bc44ca02-60c1-4593-a0fe-7856625fe0e7" />
      </body>
      <title>The beauty of yield statement</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,bc44ca02-60c1-4593-a0fe-7856625fe0e7.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/18/TheBeautyOfYieldStatement.aspx</link>
      <pubDate>Sat, 18 Oct 2008 22:35:26 GMT</pubDate>
      <description>&lt;p&gt;
How many of you played with &lt;a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx"&gt;C#
yield statement&lt;/a&gt; ? I guess that most of you did. 
&lt;br&gt;
Anyway, like most of the MSDN examples out there, when used incorrectly, it could
introduce &lt;em&gt;very&lt;/em&gt; bad behavior to your code. Consider the following:
&lt;/p&gt;
&lt;p&gt;
public IEnumerable&amp;lt;User&amp;gt; GetUsers(int count)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; using (MysqlConnection connection = new MysqlConnection("..."))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // MysqlDataReader reader = create an MysqlCommand
and execute it&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (reader.Read())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return new
User(/*... fill parameters from the reader ... */);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
} 
&lt;p&gt;
Looks pretty harmless right? Not quite. The yield statement is actually transformed
to a "state machine" which means that every time we yield a result back to the client
(the caller of GetUsers in our example), we &lt;strong&gt;wait&lt;/strong&gt; for the client to
call to the next item (via IEnumerator&amp;lt;T&amp;gt;.MoveNext()). &lt;strong&gt;The code above
will hold the connection open until the client done iterating all of the User items&lt;/strong&gt;.
This will lead into major scalability issues very quickly! You should always keep
your DB connections open for short period to prevent connection exhaustion (threads
waiting for available DB connection in the pool for long period, until timeout). Because
yield returns the control &lt;strong&gt;to the caller&lt;/strong&gt;, it might be that the caller
will "take his time" thus leading to connection exhaustion.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
On the other hand, used wisely and &lt;em&gt;yield&lt;/em&gt; yields (lame joke, sorry) &lt;em&gt;HUGE&lt;/em&gt; benefits:&lt;br&gt;
[note: code written in notepad, stupidity won't compile]
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid &lt;em&gt;useless&lt;/em&gt; memory allocations&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;#1:&lt;/strong&gt;
&lt;br&gt;
How many times you end up creating something like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public List&amp;lt;T&amp;gt; Filter(List&amp;lt;T&amp;gt; input, Predicate&amp;lt;T&amp;gt;
predicate)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;T&amp;gt; output = new List&amp;lt;T&amp;gt;(input.Count
/2);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T item in input)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (predicate(item))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output.Add(item); 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return output;&lt;br&gt;
&amp;nbsp;&amp;nbsp; } 
&lt;p&gt;
We allocate much more memory than we need only to hold the output during the calculation.
A better approach will be:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerator&amp;lt;T&amp;gt; Filter(IEnumerator&amp;lt;T&amp;gt; input,
Predicate&amp;lt;T&amp;gt; predicate)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T item in input)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (predicate(item))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return
item;&lt;br&gt;
&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
This way we allocate only &lt;strong&gt;one&lt;/strong&gt; T at a time (will be saved in the generated
state machine). In addition, the client could choose to send each item via yield as
well, thus saving the need to create the "input" before calling our Filter method.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;
&lt;br&gt;
#2:&lt;/strong&gt;
&lt;br&gt;
Another oh-(gosh-why)-so-common example is the following:
&lt;/p&gt;
&lt;p&gt;
public void Save(T item)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Save(new T[] { item });&lt;br&gt;
} 
&lt;p&gt;
public void Save(ICollection&amp;lt;T&amp;gt; items)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // do your magic here to save items&lt;br&gt;
} 
&lt;p&gt;
Assuming you call Save with a single item quite a lot, you're allocating &lt;strong&gt;A
LOT&lt;/strong&gt; of memory to create one-item arrays. A better approach will be:
&lt;/p&gt;
&lt;p&gt;
public void Save(T item)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Save(Yield.One(item));&lt;br&gt;
} 
&lt;p&gt;
public void Save(IEnumerator&amp;lt;T&amp;gt; items)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; // do your magic here to save items&lt;br&gt;
} 
&lt;p&gt;
public static class Yield&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerator&amp;lt;T&amp;gt; One&amp;lt;T&amp;gt;(T item)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield item;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
} 
&lt;p&gt;
~Zero memory allocation here.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid "impossible" memory allocation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Let's say you want to read a 20G file with emails where every line holds a single
email. Trying to declare a List&amp;lt;string&amp;gt; and filling it up will make your memory
blow up obviously. You simply can't hold that much in memory. Instead, you can use
Stream.ReadLine and yield back each row to your client, until all of the emails are
taken care of. Yes, you can try to read the file in chunks (keeping a pointer), but
this is exactly what yield does under the hood. Reminder: DRY principle is gold (or
Don't Repeat .Net Framework, in our case).
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Execute synchronous&lt;/strong&gt; &lt;strong&gt;code asynchronously&lt;/strong&gt; (nicely
achieved via &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163556.aspx"&gt;CCR&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
A bit advanced, but you can read all about it &lt;a href="http://msdn.microsoft.com/en-us/library/bb648753.aspx"&gt;here&lt;/a&gt;.
The great benefit is you can transform (almost) any "yield based" code to run async,
if needed/wanted.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;
&lt;br&gt;
Recap:&lt;br&gt;
&lt;/strong&gt;Prefer using the yield statement as long as calculating values doesn't require &lt;strong&gt;holding&lt;/strong&gt; an
expensive resource like a DB connection, or a FileHandler for &lt;strong&gt;long period
of time&lt;/strong&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=bc44ca02-60c1-4593-a0fe-7856625fe0e7" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,bc44ca02-60c1-4593-a0fe-7856625fe0e7.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=dba7a00e-808e-4bd7-9dd1-eb028d187db2</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,dba7a00e-808e-4bd7-9dd1-eb028d187db2.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,dba7a00e-808e-4bd7-9dd1-eb028d187db2.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=dba7a00e-808e-4bd7-9dd1-eb028d187db2</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
It seems that there are MANY ways to perform http web request poorly. This is a huge
problem in today's world where web-services are more common than <a href="http://www.google.co.il/url?sa=t&amp;source=web&amp;ct=res&amp;cd=3&amp;url=http%3A%2F%2Fwww.marketoracle.co.uk%2FArticle6749.html&amp;ei=YbP0SJ7XHJfuwwGygOnUDg&amp;usg=AFQjCNFSfskKYI7noMHYim0BcSvcrFA47g&amp;sig2=5-xiW6L0aL8bzJOewhrVrw">bankrupt
banks</a>. Here is a quick pattern of how to do it right:
</p>
        <p>
public string Fetch(Uri requestUri)<br />
{
</p>
        <blockquote>
          <p>
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
</p>
        </blockquote>
        <blockquote>
          <p>
webRequest.Timeout = <strong>requestConnectTimeoutInMs</strong>; // take timeout from
config<br />
webRequest.ReadWriteTimeout = <strong>requestReadWriteTimeoutInMs</strong>; // take
timeout from config
</p>
        </blockquote>
        <blockquote>
          <p>
            <strong>using</strong> (WebResponse webResponse = webRequest.GetResponse())<br /><strong>using</strong> (StreamReader streamReader = new StreamReader(new <strong>TimeoutStream</strong>(webResponse.GetResponseStream(), <strong>fetchTimeoutInMs</strong>))
// take timeout from config<br />
     return streamReader.ReadToEnd();
</p>
        </blockquote>
        <p>
}
</p>
        <p>
          <strong>Details:</strong>
        </p>
        <ol>
          <li>
Setting Timeout property: to make sure we don't wait the default 100 seconds for "ACK"
from the server. WAY too much.</li>
          <li>
Setting ReadWriteTimeout: This is crucial to understand. StreamReader under the hood
read data in chunks, this timeout determine how much time you should wait for reading
a <em>single chunk</em>. 100 seconds, the default value, is again WAY too much.</li>
          <li>
Using TimeoutStream (you need to implement your own or let me know if you're interested
and I'll send it to you): Alright, let's say you're willing to wait for 500ms for
ACK (Timeout), up to 500ms for reading every chunk (ReadWriteTimeout) but not more
than 5 seconds for the <em>entire read</em> to complete. There is no way to achieve
it without TimeoutStream. It will start a timer internally and override Seek/Read/Write
(etc) method by checking the timer <strong>before</strong> calling the internal stream
method. TimeoutStream is a very simple wrapper around Stream. For example:</li>
        </ol>
        <p>
   public override int Read(byte[] buffer, int offset, int count)<br />
      {<br />
          CheckTimeout(); // throw TimeoutException
if timeout was reached<br />
          return _stream.Read(buffer,
offset, count);<br />
      }
</p>
        <p>
          <strong>Multiple HttpWebRequest limitation:<br /></strong>By default, you can't perform more than 2-3 async HttpWebRequest (depends
on the OS). In order to override it (the easiest way, IMHO) don't forget to add this
under &lt;configuration&gt; section in the application's config file:
</p>
        <p>
&lt;system.net&gt;<br />
  &lt;connectionManagement&gt;<br />
     &lt;add address="*" maxconnection="65000" /&gt;<br />
  &lt;/connectionManagement&gt;<br />
&lt;/system.net&gt;<br /><strong><br />
Why should you follow these guidelines:</strong></p>
        <ol>
          <li>
Never trust 3rd party components: avoid excuses like "my site is not responsive because
1000 threads are waiting for web-service-X to respond". By setting those parameters
you're safe to make your own choices of how much time to wait. Log and monitor these
things to adjust your application and alert your suppliers.</li>
          <li>
Be able to determine your own SLA for the world: again, if internally you need to
call a web-service, make sure you're able to control the time you're willing to spend.
You've got clients to serve and they want you to meet the SLA as you promised! 
</li>
        </ol>
        <p>
          <strong>Important note about recycling HttpWebRequest.GetResposne()<br /></strong>Simply put, it's not working <em>by design</em>. That means that if you fail
to get a response on time (due to 1,2 or 3), don't call the webRequest.GetResponse()
again as it is cached internally (you'll get the same HttpWebResposne). What you should
do is to re-create the HttpWebRequest and try again. I don't agree with the selected
design by Microsoft for this method, but at least it's good to be aware of it.
</p>
        <p>
   from <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx">MSDN</a>: 
</p>
        <p>
   " Multiple calls to GetResponse return the same response object; the
request is not reissued. " 
</p>
        <p>
          <strong>Final note:<br /></strong>You should obviously consider writing a HttpWebRequestHelper class (or extension
method) and use it instead of copy&amp;paste this code all over your codebase.
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=dba7a00e-808e-4bd7-9dd1-eb028d187db2" />
      </body>
      <title>HttpWebRequest, avoiding the pitfalls</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,dba7a00e-808e-4bd7-9dd1-eb028d187db2.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/14/HttpWebRequestAvoidingThePitfalls.aspx</link>
      <pubDate>Tue, 14 Oct 2008 15:32:25 GMT</pubDate>
      <description>&lt;p&gt;
It seems that there are MANY ways to perform http web request poorly. This is a huge
problem in today's world where web-services are more common than &lt;a href="http://www.google.co.il/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=3&amp;amp;url=http%3A%2F%2Fwww.marketoracle.co.uk%2FArticle6749.html&amp;amp;ei=YbP0SJ7XHJfuwwGygOnUDg&amp;amp;usg=AFQjCNFSfskKYI7noMHYim0BcSvcrFA47g&amp;amp;sig2=5-xiW6L0aL8bzJOewhrVrw"&gt;bankrupt
banks&lt;/a&gt;. Here is a quick pattern of how to do it right:
&lt;/p&gt;
&lt;p&gt;
public string Fetch(Uri requestUri)&lt;br&gt;
{
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
webRequest.Timeout = &lt;strong&gt;requestConnectTimeoutInMs&lt;/strong&gt;; // take timeout from
config&lt;br&gt;
webRequest.ReadWriteTimeout = &lt;strong&gt;requestReadWriteTimeoutInMs&lt;/strong&gt;; // take
timeout from config
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;using&lt;/strong&gt; (WebResponse webResponse = webRequest.GetResponse())&lt;br&gt;
&lt;strong&gt;using&lt;/strong&gt; (StreamReader streamReader = new StreamReader(new &lt;strong&gt;TimeoutStream&lt;/strong&gt;(webResponse.GetResponseStream(), &lt;strong&gt;fetchTimeoutInMs&lt;/strong&gt;))
// take timeout from config&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return streamReader.ReadToEnd();
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Details:&lt;/strong&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Setting Timeout property: to make sure we don't wait the default 100 seconds for "ACK"
from the server. WAY too much.&lt;/li&gt;
&lt;li&gt;
Setting ReadWriteTimeout: This is crucial to understand. StreamReader under the hood
read data in chunks, this timeout determine how much time you should wait for reading
a &lt;em&gt;single chunk&lt;/em&gt;. 100 seconds, the default value, is again WAY too much.&lt;/li&gt;
&lt;li&gt;
Using TimeoutStream (you need to implement your own or let me know if you're interested
and I'll send it to you): Alright, let's say you're willing to wait for 500ms for
ACK (Timeout), up to 500ms for reading every chunk (ReadWriteTimeout) but not more
than 5 seconds for the &lt;em&gt;entire read&lt;/em&gt; to complete. There is no way to achieve
it without TimeoutStream. It will start a timer internally and override Seek/Read/Write
(etc) method by checking the timer &lt;strong&gt;before&lt;/strong&gt; calling the internal stream
method. TimeoutStream is a very simple wrapper around Stream. For example:&lt;/li&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp; public override int Read(byte[] buffer, int offset, int count)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CheckTimeout(); // throw TimeoutException
if timeout was reached&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _stream.Read(buffer,
offset, count);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&gt;
&lt;p&gt;
&lt;strong&gt;Multiple HttpWebRequest limitation:&lt;br&gt;
&lt;/strong&gt;By default, you can't perform more than 2-3 async HttpWebRequest (depends
on the OS). In order to override it (the easiest way, IMHO) don't forget to add this
under &amp;lt;configuration&amp;gt; section in the application's config file:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;system.net&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;connectionManagement&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add address="*" maxconnection="65000" /&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;/connectionManagement&amp;gt;&lt;br&gt;
&amp;lt;/system.net&amp;gt;&lt;br&gt;
&lt;strong&gt;
&lt;br&gt;
Why should you follow these guidelines:&lt;/strong&gt; 
&lt;ol&gt;
&lt;li&gt;
Never trust 3rd party components: avoid excuses like "my site is not responsive because
1000 threads are waiting for web-service-X to respond". By setting those parameters
you're safe to make your own choices of how much time to wait. Log and monitor these
things to adjust your application and alert your suppliers.&lt;/li&gt;
&lt;li&gt;
Be able to determine your own SLA for the world: again, if internally you need to
call a web-service, make sure you're able to control the time you're willing to spend.
You've got clients to serve and they want you to meet the SLA as you promised! 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;strong&gt;Important note about recycling HttpWebRequest.GetResposne()&lt;br&gt;
&lt;/strong&gt;Simply put, it's not working &lt;em&gt;by design&lt;/em&gt;. That means that if you fail
to get a response on time (due to 1,2 or 3), don't call the webRequest.GetResponse()
again as it is cached internally (you'll get the same HttpWebResposne). What you should
do is to re-create the HttpWebRequest and try again. I don't agree with the selected
design by Microsoft for this method, but at least it's good to be aware of it.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp; from &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx"&gt;MSDN&lt;/a&gt;: 
&lt;p&gt;
&amp;nbsp;&amp;nbsp; " Multiple calls to GetResponse return the same response object; the
request is not reissued. " 
&lt;p&gt;
&lt;strong&gt;Final note:&lt;br&gt;
&lt;/strong&gt;You should obviously consider writing a HttpWebRequestHelper class (or extension
method) and use it instead of copy&amp;amp;paste this code all over your codebase.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=dba7a00e-808e-4bd7-9dd1-eb028d187db2" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,dba7a00e-808e-4bd7-9dd1-eb028d187db2.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=40072280-5777-4723-b001-51f1b086cd3d</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,40072280-5777-4723-b001-51f1b086cd3d.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,40072280-5777-4723-b001-51f1b086cd3d.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=40072280-5777-4723-b001-51f1b086cd3d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
[ <a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
1</a>, this is <a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
2</a>, <a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
3</a> ]
</p>
        <p>
In <a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
1</a> I've talked about the general notions behind SpawnEnumerator and played with
the API. If you're not familiar with Microsoft's CCR, this post might require a 2nd
&amp; 3rd read to understand completely. CCR changed the way you should think or address
async code. It's a game worth playing and studying the rules is only for your advantage.
Alright, enough chit chat, let's make it happen (complete code attached at the end).<br /><br /><strong>Class definition:</strong></p>
        <p>
  public sealed class SpawnEnumerator&lt;T&gt; : IDisposable<br />
       private SpawnEnumerator(int threadsCount, string
threadsPoolName, IEnumerator&lt;T&gt; filler) { /* initialize fields by parameters,
nothing more */ }
</p>
        <p>
          <strong>Now, let's have a look at <em>some</em> of the fields: </strong>
        </p>
        <p>
  private const double DefaultLowThresholdPrcentage = 0.1; // When "items to
process" queue reach 10%, we want to re-fill. Should be exposed of course.
</p>
        <p>
  private event Action&lt;DateTime&gt; _enumeratorDepleted = delegate { }; //
trigger when the enumerator is empty<br />
  private event Action&lt;DateTime&gt; _allTasksAreCompleted = delegate { };
// trigger when all tasks are completed
</p>
        <p>
  private readonly Dispatcher _dispatcher; // our "threadpool"<br />
  private readonly DispatcherQueue _dispatcherQueue; // hold actual ITask, waiting
for the dispatcher (aka worker threads) to handle them. more about it soon. 
</p>
        <p>
  private readonly Port&lt;T&gt; _itemsToProcessPort;  // hold wannabe tasks,
currently a queue of items of T we want to process. 
<br />
  private readonly Port&lt;EmptyValue&gt; _itemCompleteNotificationPort; // soon...<br />
  private readonly Port&lt;EmptyValue&gt; _initializePort;  // soon... 
</p>
        <p>
  private readonly IEnumerator&lt;T&gt; _enumerator; // the enumerator we'll
use to fill the _itemsToProcessPort
</p>
        <p>
          <strong>Deeper look on what we have so far:</strong>
        </p>
        <ul>
          <li>
_itemsToProcessPort: will act as the queue of items we want to process. In CCR's world,
Port&lt;T&gt; is actually a "smart queue" (more on it later). 
</li>
          <li>
_itemCompleteNotificationPort: will be used to notify on every <em>completed item</em>.
Assuming that we need to fill 100 items to the port, and our lower limit is 10%, we
want to re-fill the _itemsToProcessPort every 90 completed items. Notice we're using
EmptyValue as T. EmptyValue is a CCR type that holds EmptyValue.SharedInstance to
avoid memory allocation. 
</li>
          <li>
_initializePort: will be used to initialize the _itemsToProcessPort with the 1st bulk
of items. 
</li>
        </ul>
        <p>
          <strong>Step back, what's going on?!!? why so many Port ?</strong>
          <br />
Well, the idea behind CCR is all about <em>messaging</em>. You can pass messages to
ports (Port&lt;T&gt; is thread-safe of course) and by doing so, you can take advantage
of the "smart queue" implementation behind Port&lt;T&gt;. When posting a message to
a port, the CCR will try to apply some "predicates" on the port and if a "predicate"
returns true, it will dequeue the item(s) from the Port matched that "predicate",
create an ITask of it and push it into the DispatcherQueue as an "actual task". 
</p>
        <p>
Using Ports makes it easier for us to define complex async code. instead of putting
locks all over the place, I can simply post a message to _itemCompleteNotificationPort
and after X messages posted to this port, ask to re-fill the queue when a thread is
available. This is much easier then counting each completed item and if ((counter
% X) == 0), lock some object and re-fill. Both will work, but using the CCR world
you don't have to think about <strong>technical async problems/solutions</strong> but
rather on the <strong>logical async operations</strong> you want to perform. You'll
write much less code, zero locks <em>of your own</em> and mostly think about "this
could run concurrently", "this must run exclusively" and let the CCR schedule everything
for you. 
</p>
        <p>
          <strong>Start method:</strong> (as discussed in Part 1)<br />
public static SpawnEnumerator&lt;T&gt; Start(int threadsCount, string threadsPoolName,
int upperQueueSize, IEnumerable&lt;T&gt; filler, Action&lt;T&gt; handler)<br />
{<br />
  // .. validate parameters, nothing interesting... 
<br />
  SpawnEnumerator&lt;T&gt; sw = new SpawnEnumerator&lt;T&gt;(threadsCount, threadsPoolName,
filler.GetEnumerator());<br />
  sw.Initialize(handler, upperQueueSize); 
<br />
  return sw;<br />
}
</p>
        <p>
          <strong>API Design: Why Start method with private constructor instead of public constructor
alone:</strong>
          <br />
The client of this method should understand that once she supply the arguments, things
will start happening - we'll immediately start to process items from the enumerator.
You'll soon find out that Start is non-blocking method. This "Start" method, so I
feel, make it's it more explicit as it should be. 
</p>
        <p>
          <strong>Initialize method:</strong>
          <br />
private void Initialize(Action&lt;T&gt; handler, int upperQueueSize)<br />
{<br />
  RegisterRecievers(handler, upperQueueSize); // where CCR *<em>magic</em>* happens.
soon...<br />
  _initializePort.Post(EmptyValue.SharedInstance); // post a message to let "someone"
know we want to fill the 1st bulk of items<br />
}
</p>
        <p>
          <strong>RegisterRecievers method:<br /></strong>Before we look at the code, here is a remainder of the main things we want
to accomplish:
</p>
        <ol>
          <li>
We should fill the _itemsToProcessPort for the 1st bulk or once we reach the lower
limit of the queue, by counting how many items were completed. Keeping in mind that
_enumerator is not thread-safe and we don't want to start locking access to it <em>on
our own</em>, we should make sure that re-filling is done <strong>exclusively</strong> from
1 thread only. 
</li>
          <li>
We want to handle each one of the items posted to _itemsToProcessPort with the supplied
"handler" (given in Start method). Each item is independent so obviously we want to
process each item <strong>concurrently</strong>, according to the amount of threads
in the Dispatcher.</li>
        </ol>
        <p>
private void RegisterRecievers(Action&lt;T&gt; handler, int upperQueueSize)<br />
{<br />
  int numberOfItemsToDepleteBeforePushingNewBulk = (int)Math.Ceiling((1 - DefaultLowThresholdPrcentage)
* upperQueueSize); 
</p>
        <p>
  Arbiter.Activate(_dispatcherQueue, 
</p>
        <p>
     Arbiter.Interleave(<br />
         new TeardownReceiverGroup(),// nothing
here<br />
         new ExclusiveReceiverGroup(<br />
               
// 1st bulk:<br />
               
Arbiter.Receive(false, _initializePort, delegate { FillItemsToProcessQueueWithNextBulk(upperQueueSize);
}), // only once, that's why the "false" is here.<br /><br />
               
// enough items were completed which means "items to process" queue reached lower
limit:<br />
               
Arbiter.MultipleItemReceive(true, _itemCompleteNotificationPort, numberOfItemsToDepleteBeforePushingNewBulk, 
<br />
                                         
delegate { FillItemsToProcessQueueWithNextBulk(upperQueueSize); })<br />
            ),<br />
         new ConcurrentReceiverGroup(<br />
               
// process items concurrently<br />
               
Arbiter.Receive(true, _itemsToProcessPort, // listen to <em>every</em> post, that's
why the "true"<br />
                    
delegate(T item)<br />
                    
{<br />
                        
try<br />
                        
{<br />
                            
handler(item); 
<br />
                        
}<br />
                        
catch (Exception err) { /* log error */ }<br />
                        
finally<br />
                        
{<br />
                            
HandleCompletedItem();<br />
                        
}<br />
                    
})<br />
            )<br />
        )<br />
    );<br />
}
</p>
        <p>
Alright, this is a bit harder to read but let's try to simplify it by reading it from
inside-out. 
</p>
        <ul>
          <li>
Under ExclusiveReceiverGroup you'll see 2 receivers, one that listen to _initalizePort
and once a message is posted, it will create an ITask that internally (when a thread
is available) call FillItemsToProcessQueueWithNextBulk method. The second receiver
will listen to _itemCompleteNotificationPort and do the same as the first one for
every numberOfItemsToDepleteBeforePushingNewBulk items posted to the Port. 
</li>
          <li>
Under ConcurrentReceiverGroup you'll see a receiver listening to _itemsToProcessPort
and for every message it will create an ITask that internally (again, one a thread
is available) will run the given "item handler" with the item dequeued from the Port. 
</li>
          <li>
We use Arbiter.Activate(_dispatcherQueue, ...) to register each created ITask from
the receivers to the internal queue. Queue of actual tasks. 
</li>
          <li>
This method is <strong>non-blocking</strong>, we only register receivers that know
how to create and enqueue ITask from messages posted to some Port. That's it.</li>
        </ul>
        <p>
          <strong>Recap:</strong>
          <br />
We post messages to different Port&lt;T&gt; and write receivers that "listen" to the
messages based on some rules (one receiver listen to every message, one listen to
only one message, one listen to X messages etc). When the receiver's rules apply,
the CCR will dequeue all the relevant (applied the rule) messages from the Port&lt;T&gt;
and wrap them with the supplied delegated as ITask. This ITask instance will be enqueued
to the DispatcherQueue until the Dispatcher have a free thread to handle it. The Dispatcher,
according to the <strong>requested scheduling</strong> (some ITask must run exclusively,
some can run concurrently, as we've seen), will execute those tasks.
</p>
        <p>
          <br />
You can download the complete code (with some extra features) here: <a href="http://www.lnbogen.com/content/binary/SpawnEnumerator.txt">SpawnEnumerator.txt</a> (12KB)
- you'll need CCR &amp; log4net dll in order to compile it.
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=40072280-5777-4723-b001-51f1b086cd3d" />
      </body>
      <title>Part2: SpawnEnumerator, dealing with billions of independent items</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,40072280-5777-4723-b001-51f1b086cd3d.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/14/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx</link>
      <pubDate>Tue, 14 Oct 2008 14:07:52 GMT</pubDate>
      <description>&lt;p&gt;
[ &lt;a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
1&lt;/a&gt;, this is &lt;a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
2&lt;/a&gt;, &lt;a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
3&lt;/a&gt; ]
&lt;/p&gt;
&lt;p&gt;
In &lt;a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
1&lt;/a&gt; I've talked about the general notions behind SpawnEnumerator and played with
the API. If you're not familiar with Microsoft's CCR, this post might require a 2nd
&amp;amp; 3rd read to understand completely. CCR changed the way you should think or address
async code. It's a game worth playing and studying the rules is only for your advantage.
Alright, enough chit chat, let's make it happen (complete code attached at the end).&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;Class definition:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; public sealed class SpawnEnumerator&amp;lt;T&amp;gt; : IDisposable&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private SpawnEnumerator(int threadsCount, string
threadsPoolName, IEnumerator&amp;lt;T&amp;gt; filler) { /* initialize fields by parameters,
nothing more */ }
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Now, let's have a look at &lt;em&gt;some&lt;/em&gt; of the fields: &lt;/strong&gt; 
&lt;p&gt;
&amp;nbsp; private const double DefaultLowThresholdPrcentage = 0.1; // When "items to
process" queue reach 10%, we want to re-fill. Should be exposed of course.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; private event Action&amp;lt;DateTime&amp;gt; _enumeratorDepleted = delegate { }; //
trigger when the enumerator is empty&lt;br&gt;
&amp;nbsp; private event Action&amp;lt;DateTime&amp;gt; _allTasksAreCompleted = delegate { };
// trigger when all tasks are completed
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; private readonly Dispatcher _dispatcher; // our "threadpool"&lt;br&gt;
&amp;nbsp; private readonly DispatcherQueue _dispatcherQueue; // hold actual ITask, waiting
for the dispatcher (aka worker threads) to handle them. more about it soon. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; private readonly Port&amp;lt;T&amp;gt; _itemsToProcessPort;&amp;nbsp; // hold wannabe tasks,
currently a queue of items of T we want to process. 
&lt;br&gt;
&amp;nbsp; private readonly Port&amp;lt;EmptyValue&amp;gt; _itemCompleteNotificationPort; // soon...&lt;br&gt;
&amp;nbsp; private readonly Port&amp;lt;EmptyValue&amp;gt; _initializePort;&amp;nbsp; // soon... 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; private readonly IEnumerator&amp;lt;T&amp;gt; _enumerator; // the enumerator we'll
use to fill the _itemsToProcessPort
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Deeper look on what we have so far:&lt;/strong&gt; 
&lt;ul&gt;
&lt;li&gt;
_itemsToProcessPort: will act as the queue of items we want to process. In CCR's world,
Port&amp;lt;T&amp;gt; is actually a "smart queue" (more on it later). 
&lt;li&gt;
_itemCompleteNotificationPort: will be used to notify on every &lt;em&gt;completed item&lt;/em&gt;.
Assuming that we need to fill 100 items to the port, and our lower limit is 10%, we
want to re-fill the _itemsToProcessPort every 90 completed items. Notice we're using
EmptyValue as T. EmptyValue is a CCR type that holds EmptyValue.SharedInstance to
avoid memory allocation. 
&lt;li&gt;
_initializePort: will be used to initialize the _itemsToProcessPort with the 1st bulk
of items. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;strong&gt;Step back, what's going on?!!? why so many Port ?&lt;/strong&gt; 
&lt;br&gt;
Well, the idea behind CCR is all about &lt;em&gt;messaging&lt;/em&gt;. You can pass messages to
ports (Port&amp;lt;T&amp;gt; is thread-safe of course) and by doing so, you can take advantage
of the "smart queue" implementation behind Port&amp;lt;T&amp;gt;. When posting a message to
a port, the CCR will try to apply some "predicates" on the port and if a "predicate"
returns true, it will dequeue the item(s) from the Port matched that "predicate",
create an ITask of it and push it into the DispatcherQueue as an "actual task". 
&lt;/p&gt;
&lt;p&gt;
Using Ports makes it easier for us to define complex async code. instead of putting
locks all over the place, I can simply post a message to _itemCompleteNotificationPort
and after X messages posted to this port, ask to re-fill the queue when a thread is
available. This is much easier then counting each completed item and if ((counter
% X) == 0), lock some object and re-fill. Both will work, but using the CCR world
you don't have to think about &lt;strong&gt;technical async problems/solutions&lt;/strong&gt; but
rather on the &lt;strong&gt;logical async operations&lt;/strong&gt; you want to perform. You'll
write much less code, zero locks &lt;em&gt;of your own&lt;/em&gt; and mostly think about "this
could run concurrently", "this must run exclusively" and let the CCR schedule everything
for you. 
&lt;p&gt;
&lt;strong&gt;Start method:&lt;/strong&gt; (as discussed in Part 1)&lt;br&gt;
public static SpawnEnumerator&amp;lt;T&amp;gt; Start(int threadsCount, string threadsPoolName,
int upperQueueSize, IEnumerable&amp;lt;T&amp;gt; filler, Action&amp;lt;T&amp;gt; handler)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp; // .. validate parameters, nothing interesting... 
&lt;br&gt;
&amp;nbsp; SpawnEnumerator&amp;lt;T&amp;gt; sw = new SpawnEnumerator&amp;lt;T&amp;gt;(threadsCount, threadsPoolName,
filler.GetEnumerator());&lt;br&gt;
&amp;nbsp; sw.Initialize(handler, upperQueueSize); 
&lt;br&gt;
&amp;nbsp; return sw;&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;API Design: Why Start method with private constructor instead of public constructor
alone:&lt;/strong&gt; 
&lt;br&gt;
The client of this method should understand that once she supply the arguments, things
will start happening - we'll immediately start to process items from the enumerator.
You'll soon find out that Start is non-blocking method. This "Start" method, so I
feel, make it's it more explicit as it should be. 
&lt;p&gt;
&lt;strong&gt;Initialize method:&lt;/strong&gt; 
&lt;br&gt;
private void Initialize(Action&amp;lt;T&amp;gt; handler, int upperQueueSize)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp; RegisterRecievers(handler, upperQueueSize); // where CCR *&lt;em&gt;magic&lt;/em&gt;* happens.
soon...&lt;br&gt;
&amp;nbsp; _initializePort.Post(EmptyValue.SharedInstance); // post a message to let "someone"
know we want to fill the 1st bulk of items&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;RegisterRecievers method:&lt;br&gt;
&lt;/strong&gt;Before we look at the code, here is a remainder of the main things we want
to accomplish:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
We should fill the _itemsToProcessPort for the 1st bulk or once we reach the lower
limit of the queue, by counting how many items were completed. Keeping in mind that
_enumerator is not thread-safe and we don't want to start locking access to it &lt;em&gt;on
our own&lt;/em&gt;, we should make sure that re-filling is done &lt;strong&gt;exclusively&lt;/strong&gt; from
1 thread only. 
&lt;li&gt;
We want to handle each one of the items posted to _itemsToProcessPort with the supplied
"handler" (given in Start method). Each item is independent so obviously we want to
process each item &lt;strong&gt;concurrently&lt;/strong&gt;, according to the amount of threads
in the Dispatcher.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
private void RegisterRecievers(Action&amp;lt;T&amp;gt; handler, int upperQueueSize)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp; int numberOfItemsToDepleteBeforePushingNewBulk = (int)Math.Ceiling((1 - DefaultLowThresholdPrcentage)
* upperQueueSize); 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; Arbiter.Activate(_dispatcherQueue, 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Arbiter.Interleave(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new TeardownReceiverGroup(),// nothing
here&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ExclusiveReceiverGroup(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// 1st bulk:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Arbiter.Receive(false, _initializePort, delegate { FillItemsToProcessQueueWithNextBulk(upperQueueSize);
}), // only once, that's why the "false" is here.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// enough items were completed which means "items to process" queue reached lower
limit:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Arbiter.MultipleItemReceive(true, _itemCompleteNotificationPort, numberOfItemsToDepleteBeforePushingNewBulk, 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delegate { FillItemsToProcessQueueWithNextBulk(upperQueueSize); })&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ConcurrentReceiverGroup(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// process items concurrently&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Arbiter.Receive(true, _itemsToProcessPort, // listen to &lt;em&gt;every&lt;/em&gt; post, that's
why the "true"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delegate(T item)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
handler(item); 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
catch (Exception err) { /* log error */ }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
finally&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
HandleCompletedItem();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
})&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br&gt;
}
&lt;/p&gt;
&lt;p&gt;
Alright, this is a bit harder to read but let's try to simplify it by reading it from
inside-out. 
&lt;ul&gt;
&lt;li&gt;
Under ExclusiveReceiverGroup you'll see 2 receivers, one that listen to _initalizePort
and once a message is posted, it will create an ITask that internally (when a thread
is available) call FillItemsToProcessQueueWithNextBulk method. The second receiver
will listen to _itemCompleteNotificationPort and do the same as the first one for
every numberOfItemsToDepleteBeforePushingNewBulk items posted to the Port. 
&lt;li&gt;
Under ConcurrentReceiverGroup you'll see a receiver listening to _itemsToProcessPort
and for every message it will create an ITask that internally (again, one a thread
is available) will run the given "item handler" with the item dequeued from the Port. 
&lt;li&gt;
We use Arbiter.Activate(_dispatcherQueue, ...) to register each created ITask from
the receivers to the internal queue. Queue of actual tasks. 
&lt;li&gt;
This method is &lt;strong&gt;non-blocking&lt;/strong&gt;, we only register receivers that know
how to create and enqueue ITask from messages posted to some Port. That's it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;strong&gt;Recap:&lt;/strong&gt; 
&lt;br&gt;
We post messages to different Port&amp;lt;T&amp;gt; and write receivers that "listen" to the
messages based on some rules (one receiver listen to every message, one listen to
only one message, one listen to X messages etc). When the receiver's rules apply,
the CCR will dequeue all the relevant (applied the rule) messages from the Port&amp;lt;T&amp;gt;
and wrap them with the supplied delegated as ITask. This ITask instance will be enqueued
to the DispatcherQueue until the Dispatcher have a free thread to handle it. The Dispatcher,
according to the &lt;strong&gt;requested scheduling&lt;/strong&gt; (some ITask must run exclusively,
some can run concurrently, as we've seen), will execute those tasks.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
You can download the complete code (with some extra features) here: &lt;a href="http://www.lnbogen.com/content/binary/SpawnEnumerator.txt"&gt;SpawnEnumerator.txt&lt;/a&gt; (12KB)
- you'll need CCR &amp;amp; log4net dll in order to compile it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=40072280-5777-4723-b001-51f1b086cd3d" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,40072280-5777-4723-b001-51f1b086cd3d.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=8903eaa3-5157-4b14-8669-8b8ff4c11613</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,8903eaa3-5157-4b14-8669-8b8ff4c11613.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,8903eaa3-5157-4b14-8669-8b8ff4c11613.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8903eaa3-5157-4b14-8669-8b8ff4c11613</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
[ this is <a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
1</a>, <a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
2</a>, <a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx">Part
3</a> ]
</p>
        <p>
          <a href="http://www.lnbogen.com/DeepDiveIntoCCRAndParallelExtensionsKickoff.aspx">I
promised</a> to write more about <a href="http://msdn.microsoft.com/he-il/magazine/cc163556(en-us).aspx">CCR</a> and
how to use it in practice. 
<br />
There is no better way to explain how infrastructure work then writing some code and
play with it, so lets toy with a simple utility, based on CCR under the hood.
</p>
        <p>
          <strong>Scenario</strong>: you've got billions of *<em>independent</em>* tasks you
need to execute as fast as possible. 
<br /><strong>Requirements</strong>:
</p>
        <ol>
          <li>
Amount of "worker threads" should be easy to define. obviously. 
</li>
          <li>
Memory consumption - don't eat more than you can chew. We don't want to hold everything
in memory, this should be easy to configure. 
</li>
          <li>
The process should *<em>not</em>* shutdown due to un-handled exception in one of the
worker threads. 
</li>
          <li>
We want to know when the enumerator is depleted and/or all items were completed. This
is crucial for testing and adjusting parameters.</li>
        </ol>
        <p>
 
</p>
        <p>
The general notion behind SpawnEnumerator is something like this:<br /></p>
        <p>
          <a href="http://www.lnbogen.com/content/binary/SpawnEnumeratordealingwithbillionsofinde_D9EA/SpawnEnumerator_generalIdea.jpg">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="191" alt="SpawnEnumerator_generalIdea" src="http://www.lnbogen.com/content/binary/SpawnEnumeratordealingwithbillionsofinde_D9EA/SpawnEnumerator_generalIdea_thumb.jpg" width="645" border="0" />
          </a>
        </p>
        <p>
 
</p>
        <p>
We're pulling a bulk of items from the enumerator, each one of them is actually a
"wannabe" item. Combining the value of each T with a given "item handler" could be
transformed into an actual task, waiting for its turn in the "threads pool". Once
the port/queue of "items to execute" reach the lower limit, we'll pull another bulk
of items from the enumerator until the enumerator is depleted.
</p>
        <p>
          <br />
          <strong>API playground</strong>:
</p>
        <p>
SpawnEnumerator&lt;T&gt;.Start(int numberOfThreads, string threadPoolName, int numberOfItemsToHoldInMemory,
IEnumerator&lt;T&gt; enumerator, Action&lt;T&gt; singleItemHandler)
</p>
        <blockquote>
          <p>
T = type of items we would like to run. if we have 10,000,000 items of type int, we'll
supply "int" as T.<br />
numberOfThreads = how many worker threads do we want to run?<br />
threadPoolName = name the worker threads for easier debugging.<br />
numberOfItemsToHoldInMemory = rough number of items we want to hold in memory, to
make sure memory consumption won't blow up in our face.<br />
enumerator = the enumerator of "items" to execute, assuming that it will hold a *<em>huge</em>*
amount of tasks.<br />
singleItemHandler = delegate that receives 1 item and handle it.
</p>
        </blockquote>
        <p>
event Action&lt;DateTime&gt; EnumeratorDepleted
</p>
        <p>
event Action&lt;DateTime&gt; AllTasksAreCompleted
</p>
        <p>
          <br />
          <strong>Test playground:</strong>
        </p>
        <p>
(written in notepad, sorry for stupid mistakes) 
</p>
        <p>
[Test]<br />
public void Execute_LargeEnumeratorOfNumbers_ExecuteAllItems<br />
{
</p>
        <blockquote>
          <p>
// arrange:<br />
int numberOfThreads = 10;<br />
string threadPoolName = "mypool";<br />
int numberOfItemsToHoldInMemory = 100;<br /><br />
IEnumerator&lt;int&gt; items = Yield.For(1, 10000); // yield return numbers from 1-10000<br />
Action&lt;int&gt; singleItemHandler = delegate(int item) {  /* sum the given
number, via Interlocked.Add */ };<br /><br />
ManualResetEvent trigger = new ManualResetEvent(false); 
</p>
        </blockquote>
        <blockquote>
          <p>
// act:<br />
_executor = SpawnEnumerator&lt;int&gt;.Start(threadPoolSize, threadPoolName, numberOfItemsToHoldInMemory,
items, singleItemHandler))<br />
_executor.AllTasksAreCompleted += delegate { trigger.Set(); };    
<br /><br />
// assert:<br />
bool signaled = trigger.WaitOne(TimeSpan.FromSeconds(1), false);<br />
Assert.IsTrue(signaled, "timedout reached, that shouldn't happen!");<br />
// assert that all of the items were called by matching sum of 1-N sequential numbers
(simple formula) to what we collected in the handler
</p>
        </blockquote>
        <p>
}
</p>
        <p>
          <br />
* In the "test teardown" we can check if _executor is not null and if so Dispose it
to close the "worker threads".
</p>
        <p>
          <strong>
          </strong> 
</p>
        <p>
          <strong>Next post - Implementing SpawnEnumerator via CCR.</strong>
        </p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=8903eaa3-5157-4b14-8669-8b8ff4c11613" />
      </body>
      <title>Part1: SpawnEnumerator, dealing with billions of independent items</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,8903eaa3-5157-4b14-8669-8b8ff4c11613.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/13/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx</link>
      <pubDate>Mon, 13 Oct 2008 14:50:48 GMT</pubDate>
      <description>&lt;p&gt;
[ this is &lt;a href="http://www.lnbogen.com/Part1SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
1&lt;/a&gt;, &lt;a href="http://www.lnbogen.com/Part2SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
2&lt;/a&gt;, &lt;a href="http://www.lnbogen.com/Part3SpawnEnumeratorDealingWithBillionsOfIndependentItems.aspx"&gt;Part
3&lt;/a&gt; ]
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.lnbogen.com/DeepDiveIntoCCRAndParallelExtensionsKickoff.aspx"&gt;I
promised&lt;/a&gt; to write more about &lt;a href="http://msdn.microsoft.com/he-il/magazine/cc163556(en-us).aspx"&gt;CCR&lt;/a&gt; and
how to use it in practice. 
&lt;br&gt;
There is no better way to explain how infrastructure work then writing some code and
play with it, so lets toy with a simple utility, based on CCR under the hood.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;: you've got billions of *&lt;em&gt;independent&lt;/em&gt;* tasks you
need to execute as fast as possible. 
&lt;br&gt;
&lt;strong&gt;Requirements&lt;/strong&gt;:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Amount of "worker threads" should be easy to define. obviously. 
&lt;li&gt;
Memory consumption - don't eat more than you can chew. We don't want to hold everything
in memory, this should be easy to configure. 
&lt;li&gt;
The process should *&lt;em&gt;not&lt;/em&gt;* shutdown due to un-handled exception in one of the
worker threads. 
&lt;li&gt;
We want to know when the enumerator is depleted and/or all items were completed. This
is crucial for testing and adjusting parameters.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
The general notion behind SpawnEnumerator is something like this:&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.lnbogen.com/content/binary/SpawnEnumeratordealingwithbillionsofinde_D9EA/SpawnEnumerator_generalIdea.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="191" alt="SpawnEnumerator_generalIdea" src="http://www.lnbogen.com/content/binary/SpawnEnumeratordealingwithbillionsofinde_D9EA/SpawnEnumerator_generalIdea_thumb.jpg" width="645" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
We're pulling a bulk of items from the enumerator, each one of them is actually a
"wannabe" item. Combining the value of each T with a given "item handler" could be
transformed into an actual task, waiting for its turn in the "threads pool". Once
the port/queue of "items to execute" reach the lower limit, we'll pull another bulk
of items from the enumerator until the enumerator is depleted.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;strong&gt;API playground&lt;/strong&gt;:
&lt;/p&gt;
&lt;p&gt;
SpawnEnumerator&amp;lt;T&amp;gt;.Start(int numberOfThreads, string threadPoolName, int numberOfItemsToHoldInMemory,
IEnumerator&amp;lt;T&amp;gt; enumerator, Action&amp;lt;T&amp;gt; singleItemHandler)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
T = type of items we would like to run. if we have 10,000,000 items of type int, we'll
supply "int" as T.&lt;br&gt;
numberOfThreads = how many worker threads do we want to run?&lt;br&gt;
threadPoolName = name the worker threads for easier debugging.&lt;br&gt;
numberOfItemsToHoldInMemory = rough number of items we want to hold in memory, to
make sure memory consumption won't blow up in our face.&lt;br&gt;
enumerator = the enumerator of "items" to execute, assuming that it will hold a *&lt;em&gt;huge&lt;/em&gt;*
amount of tasks.&lt;br&gt;
singleItemHandler = delegate that receives 1 item and handle it.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
event Action&amp;lt;DateTime&amp;gt; EnumeratorDepleted
&lt;/p&gt;
&lt;p&gt;
event Action&amp;lt;DateTime&amp;gt; AllTasksAreCompleted
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;strong&gt;Test playground:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
(written in notepad, sorry for stupid mistakes) 
&lt;p&gt;
[Test]&lt;br&gt;
public void Execute_LargeEnumeratorOfNumbers_ExecuteAllItems&lt;br&gt;
{
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
// arrange:&lt;br&gt;
int numberOfThreads = 10;&lt;br&gt;
string threadPoolName = "mypool";&lt;br&gt;
int numberOfItemsToHoldInMemory = 100;&lt;br&gt;
&lt;br&gt;
IEnumerator&amp;lt;int&amp;gt; items = Yield.For(1, 10000); // yield return numbers from 1-10000&lt;br&gt;
Action&amp;lt;int&amp;gt; singleItemHandler = delegate(int item) {&amp;nbsp; /* sum the given
number, via Interlocked.Add */ };&lt;br&gt;
&lt;br&gt;
ManualResetEvent trigger = new ManualResetEvent(false); 
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
// act:&lt;br&gt;
_executor = SpawnEnumerator&amp;lt;int&amp;gt;.Start(threadPoolSize, threadPoolName, numberOfItemsToHoldInMemory,
items, singleItemHandler))&lt;br&gt;
_executor.AllTasksAreCompleted += delegate { trigger.Set(); };&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
// assert:&lt;br&gt;
bool signaled = trigger.WaitOne(TimeSpan.FromSeconds(1), false);&lt;br&gt;
Assert.IsTrue(signaled, "timedout reached, that shouldn't happen!");&lt;br&gt;
// assert that all of the items were called by matching sum of 1-N sequential numbers
(simple formula) to what we collected in the handler
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
* In the "test teardown" we can check if _executor is not null and if so Dispose it
to close the "worker threads".
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Next post - Implementing SpawnEnumerator via CCR.&lt;/strong&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=8903eaa3-5157-4b14-8669-8b8ff4c11613" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,8903eaa3-5157-4b14-8669-8b8ff4c11613.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This is mostly a self-note but heck, maybe someone will reach this post via <a href="http://www.delver.com">Delver</a> (or <a href="http://www.google.com">Google</a> :)),
so I'm all about sharing.
</p>
        <p>
Anyway, we're using (for now) Bugzilla and I tried to get all the "open" bugs for
my team with status equal to X,Y,Z. 
</p>
        <p>
Sounds easy right? well, you are ... sadly mistaken.<br />
After investing 15 minutes banging my head into the nearest wall with “Bugzilla Advanced
Serach” (well, I'll be polite and say it's "advanced" alright), I gave in on that
one.<br />
Instead, I hacked the url a bit to understand the dark voodoo of Bugzilla and voila,
2 minutes later: 
</p>
        <p>
          <a href="http://qabugz/cgi-bin/bugzilla/buglist.cgi">http://qabugz/cgi-bin/bugzilla/buglist.cgi</a>
          <br />
?bug_status=NEW<br />
&amp;bug_status=ASSIGNED<br />
&amp;bug_status=REOPENED<br />
&amp;assigned_to=Joe<br />
&amp;assigned_to=Joe2<br />
&amp;assigned_to=Joe3<br />
&amp;query_format=specific<br />
&amp;field0-0-0=bug_status<br />
&amp;field0-0-1=assigned_to<br />
&amp;type0-0-0=anyexact<br />
&amp;type0-0-1=anyexact<br />
&amp;order=bugs.bug_severity 
</p>
        <p>
          <br />
Just remove the “break line” of course (this is easier to edit) and replace "Joe"
with your favorite developer name.<br /><br />
If you want to make it a bit more complex, here is a nice site with the supported
field names:<br /><a title="http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html" href="http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html">http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html</a></p>
        <p>
 
</p>
        <p>
Anyway, I hope it will help someone.
</p>
        <p>
* geeky btw – notice the funny “binary index” of the fields! made me laugh quite a
bit, being the geek that I am.
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f" />
      </body>
      <title>Building search queries in Bugzilla</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f.aspx</guid>
      <link>http://www.lnbogen.com/2008/10/06/BuildingSearchQueriesInBugzilla.aspx</link>
      <pubDate>Mon, 06 Oct 2008 13:20:44 GMT</pubDate>
      <description>&lt;p&gt;
This is mostly a self-note but heck, maybe someone will reach this post via &lt;a href="http://www.delver.com"&gt;Delver&lt;/a&gt; (or &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt; :)),
so I'm all about sharing.
&lt;/p&gt;
&lt;p&gt;
Anyway, we're using (for now) Bugzilla and I tried to get all the "open" bugs for
my team with status equal to X,Y,Z. 
&lt;/p&gt;
&lt;p&gt;
Sounds easy right? well, you are ... sadly mistaken.&lt;br&gt;
After investing 15 minutes banging my head into the nearest wall with “Bugzilla Advanced
Serach” (well, I'll be polite and say it's "advanced" alright), I gave in on that
one.&lt;br&gt;
Instead, I hacked the url a bit to understand the dark voodoo of Bugzilla and voila,
2 minutes later: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://qabugz/cgi-bin/bugzilla/buglist.cgi"&gt;http://qabugz/cgi-bin/bugzilla/buglist.cgi&lt;/a&gt;
&lt;br&gt;
?bug_status=NEW&lt;br&gt;
&amp;amp;bug_status=ASSIGNED&lt;br&gt;
&amp;amp;bug_status=REOPENED&lt;br&gt;
&amp;amp;assigned_to=Joe&lt;br&gt;
&amp;amp;assigned_to=Joe2&lt;br&gt;
&amp;amp;assigned_to=Joe3&lt;br&gt;
&amp;amp;query_format=specific&lt;br&gt;
&amp;amp;field0-0-0=bug_status&lt;br&gt;
&amp;amp;field0-0-1=assigned_to&lt;br&gt;
&amp;amp;type0-0-0=anyexact&lt;br&gt;
&amp;amp;type0-0-1=anyexact&lt;br&gt;
&amp;amp;order=bugs.bug_severity 
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Just remove the “break line” of course (this is easier to edit) and replace "Joe"
with your favorite developer name.&lt;br&gt;
&lt;br&gt;
If you want to make it a bit more complex, here is a nice site with the supported
field names:&lt;br&gt;
&lt;a title="http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html" href="http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html"&gt;http://pkp.sfu.ca/bugzilla/page.cgi?id=quicksearchhack.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Anyway, I hope it will help someone.
&lt;/p&gt;
&lt;p&gt;
* geeky btw – notice the funny “binary index” of the fields! made me laugh quite a
bit, being the geek that I am.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,0c0d13fe-e0b9-4f15-8e10-dceacdc6e44f.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=fc9e9585-5f5e-423c-8676-524a5de0cefa</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,fc9e9585-5f5e-423c-8676-524a5de0cefa.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,fc9e9585-5f5e-423c-8676-524a5de0cefa.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=fc9e9585-5f5e-423c-8676-524a5de0cefa</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the biggest challenges in management is be able to track your own rhythm, making
sure your plans are executed and things go smoothly. 
</p>
        <p>
In my previous post about <a href="http://www.lnbogen.com/DrivenBySelfOrganization.aspx">Driven
By Self Organization</a> I stressed the importance of making things visible and plan
for the future. How can one set the environment of the team to drive the entire team
to success? 
</p>
        <p>
Thinking about it lately made me think that I have my own thoughts about what should
be visible, how the team should react internally and how should one behave in such
team as a Team Lead. Don't get me wrong, I don't have 30 years of experience leading
small&lt;-&gt;giant teams for small&lt;-&gt;giant companies, these ideas are solely
based on my gut feelings: making things SIMPLE (KISS) so the entire team will be driven
by self-organization without the "burden" of self-management. If things are easy to
do, it's easier to get better at them. 
</p>
        <p>
The trick is to <strong>allow all of the members</strong> in the team to be part of
the organize-&gt;execute game. Some will play, some won't, but they will all be affected
by the always-ready environment and notice how inner-interaction change their day.
By making it visible, they will be motivated to take action (it will feel natural).
I came up with this drawing to expose our <strong>sprint</strong> plans and progress: 
</p>
        <p>
  
</p>
        <p>
 <a href="http://www.lnbogen.com/content/binary/SelfOrganizationforDevelopmentTeams_F65E/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="437" alt="image" src="http://www.lnbogen.com/content/binary/SelfOrganizationforDevelopmentTeams_F65E/image_thumb.png" width="738" border="0" /></a></p>
        <p>
  
</p>
        <p>
This is a very SIMPLE presentation of the current sprint features and every-day progress
- "cards" will move between columns as people work on them.<br />
There are some magic "self organization" tricks integrated into this 1-Visible-view: 
</p>
        <ol>
          <li>
Achievement-based planning: Before arranging the features/cards, we try to set the
"deliveries" for the week. This is a free-text (don't be tempted to make it a list
of features) ideas to "set the mood" for the week. It will describe features we want
to finish, some design we need to handle before the next week, some quality check
we want to pass ("make sure no critical/major bugs are open") etc. They help to plan
the week as they define goals that are measurable, driving the team to achievement-based
planning rather than like-best-do-first development. 
</li>
          <li>
Visibility is key: Every member of the team knows exactly what's left for the <strong>entire</strong> team
on a weekly level. No more "but I finished all my tasks two days earlier than we've
talked! what can I do that Joe is new here and couldn't continue as you thought? oh,
I didn't know we are dependent on his task before we can release the package..." 
</li>
          <li>
Help each other: remind yourselves that things need to be completed, help one another
by helping out when someone is behind of schedule (alright Joe, I'll take Feature
A, don't worry). The board will make it easier to know "where can I help?" 
</li>
          <li>
We want Quality: Nothing is DONE until it's tested and fixed. The idea of splitting
"coded" tasks from "tested" tasks is to set the mood for "production ready" code. 
</li>
          <li>
Small goals are easier to achieve: Splitting the sprint into smaller chunks make it
easier to win small battles. Each week defines small trophies - the "deliveries" we
promised for that week. 
</li>
          <li>
Plan leftovers for tomorrow: at the end of every week\sprint, you could easily see
what was left. Discuss why it failed and plan it for <strong>tomorrow </strong>(=next
week or next sprint). 
</li>
        </ol>
        <p>
 
</p>
        <p>
Team Lead in such a team will mostly act as a coach, helping the team members to split
the features into tasks, remove obstacles, motivate cooperation and taking notes about
"how can we get better?". Most importantly, it will allow her (or him) to be productive
and feel he can help the team's effort instead of the constant-chaos feeling managers
tend to have when things go poorly. The team members are aware of the plans and can
balance the efforts to break loose of this chaos-like feeling.
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=fc9e9585-5f5e-423c-8676-524a5de0cefa" />
      </body>
      <title>Self Organization inside a Team</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,fc9e9585-5f5e-423c-8676-524a5de0cefa.aspx</guid>
      <link>http://www.lnbogen.com/2008/09/30/SelfOrganizationInsideATeam.aspx</link>
      <pubDate>Tue, 30 Sep 2008 16:07:31 GMT</pubDate>
      <description>&lt;p&gt;
One of the biggest challenges in management is be able to track your own rhythm, making
sure your plans are executed and things go smoothly. 
&lt;p&gt;
In my previous post about &lt;a href="http://www.lnbogen.com/DrivenBySelfOrganization.aspx"&gt;Driven
By Self Organization&lt;/a&gt; I stressed the importance of making things visible and plan
for the future. How can one set the environment of the team to drive the entire team
to success? 
&lt;p&gt;
Thinking about it lately made me think that I have my own thoughts about what should
be visible, how the team should react internally and how should one behave in such
team as a Team Lead. Don't get me wrong, I don't have 30 years of experience leading
small&amp;lt;-&amp;gt;giant teams for small&amp;lt;-&amp;gt;giant companies, these ideas are solely
based on my gut feelings: making things SIMPLE (KISS) so the entire team will be driven
by self-organization without the "burden" of self-management. If things are easy to
do, it's easier to get better at them. 
&lt;p&gt;
The trick is to &lt;strong&gt;allow all of the members&lt;/strong&gt; in the team to be part of
the organize-&amp;gt;execute game. Some will play, some won't, but they will all be affected
by the always-ready environment and notice how inner-interaction change their day.
By making it visible, they will be motivated to take action (it will feel natural).
I came up with this drawing to expose our &lt;strong&gt;sprint&lt;/strong&gt; plans and progress: 
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
&amp;nbsp;&lt;a href="http://www.lnbogen.com/content/binary/SelfOrganizationforDevelopmentTeams_F65E/image.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="437" alt="image" src="http://www.lnbogen.com/content/binary/SelfOrganizationforDevelopmentTeams_F65E/image_thumb.png" width="738" border="0"&gt;&lt;/a&gt; 
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
This is a very SIMPLE presentation of the current sprint features and every-day progress
- "cards" will move between columns as people work on them.&lt;br&gt;
There are some magic "self organization" tricks integrated into this 1-Visible-view: 
&lt;ol&gt;
&lt;li&gt;
Achievement-based planning: Before arranging the features/cards, we try to set the
"deliveries" for the week. This is a free-text (don't be tempted to make it a list
of features) ideas to "set the mood" for the week. It will describe features we want
to finish, some design we need to handle before the next week, some quality check
we want to pass ("make sure no critical/major bugs are open") etc. They help to plan
the week as they define goals that are measurable, driving the team to achievement-based
planning rather than like-best-do-first development. 
&lt;li&gt;
Visibility is key: Every member of the team knows exactly what's left for the &lt;strong&gt;entire&lt;/strong&gt; team
on a weekly level. No more "but I finished all my tasks two days earlier than we've
talked! what can I do that Joe is new here and couldn't continue as you thought? oh,
I didn't know we are dependent on his task before we can release the package..." 
&lt;li&gt;
Help each other: remind yourselves that things need to be completed, help one another
by helping out when someone is behind of schedule (alright Joe, I'll take Feature
A, don't worry). The board will make it easier to know "where can I help?" 
&lt;li&gt;
We want Quality: Nothing is DONE until it's tested and fixed. The idea of splitting
"coded" tasks from "tested" tasks is to set the mood for "production ready" code. 
&lt;li&gt;
Small goals are easier to achieve: Splitting the sprint into smaller chunks make it
easier to win small battles. Each week defines small trophies - the "deliveries" we
promised for that week. 
&lt;li&gt;
Plan leftovers for tomorrow: at the end of every week\sprint, you could easily see
what was left. Discuss why it failed and plan it for &lt;strong&gt;tomorrow &lt;/strong&gt;(=next
week or next sprint). 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Team Lead in such a team will mostly act as a coach, helping the team members to split
the features into tasks, remove obstacles, motivate cooperation and taking notes about
"how can we get better?". Most importantly, it will allow her (or him) to be productive
and feel he can help the team's effort instead of the constant-chaos feeling managers
tend to have when things go poorly. The team members are aware of the plans and can
balance the efforts to break loose of this chaos-like feeling.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=fc9e9585-5f5e-423c-8676-524a5de0cefa" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,fc9e9585-5f5e-423c-8676-524a5de0cefa.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=c5f0ef03-0a94-44b2-ada3-0b09c43f5a97</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,c5f0ef03-0a94-44b2-ada3-0b09c43f5a97.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,c5f0ef03-0a94-44b2-ada3-0b09c43f5a97.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c5f0ef03-0a94-44b2-ada3-0b09c43f5a97</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Think about a young fellow, wanting to get into shape. Here are 2 scenarios of how
one can tackle that wish:
</p>
        <p>
          <strong>1.</strong> Create a plan and "manage yourself" to keep it. 
</p>
        <p>
   20:00 - set the clock to 06:00<br />
   06:00 - wake up, <strong>make sure</strong> you're not falling back to
sleep! get dressed etc<br />
   06:15 - <strong>make sure</strong> to eat something small and drink some
water<br />
   06:35 - run 5km<br />
   08:00 - <strong>make sure</strong> your bag is ready for school<br />
   08:15 - go to school<br />
   ... 
<br />
   20:00 - set the clock to 06:00
</p>
        <p>
          <strong>
            <br />
2.</strong> Organize things to drive your day:
</p>
        <p>
   20:00 - put your shoes next to your bed, set your clock to 06:00 and
set it FAR from the bed, prepare a little something to eat for tomorrow morning, prepare
your bag for (tomorrow's) school.<br />
   06:00 - wake up - go close the damn clock (you need to stand in order
to do it), get dressed etc.<br />
   06:15 - eat something small and drink some water<br />
   06:35 - run 5km<br />
   08:00 - relax for a few minutes and then go to school<br />
   ... 
<br />
   20:00 - put your shoes next to your bed, set your clock to 06:00 and
set it FAR from the bed, prepare a little something to eat for tomorrow morning, prepare
your bag for (tomorrow's) school.
</p>
        <p>
          <br />
          <strong>Where most of us fail?</strong>
        </p>
        <p>
I might be wrong, but it seems that a lot of us (myself included) simply can't manage
our time wisely during the day, <strong>for long period of time</strong>. It's too
easy to forget something to do TODAY when you had to force yourself to plan it TODAY.
It's too easy to fail. It's too easy to stop the rhythm. 
<br /><br />
This is why most of us can't lose weight, can't get into shape, can't read 5 books
every month etc. 
</p>
        <p>
          <strong>
            <br />
Driven by Self-organization</strong>
        </p>
        <p>
To me, it means that I want to set <strong>my environment</strong> to drive me into
success. If I'll take the time to prepare my tomorrow, little chance I'll fail due
to laziness: (1) I'm planning for TOMORROW, so what do I care to invest the time?
I only plan things and set the environment / mood. I don't need to run the 5km now,
I only want to make sure it will be easier to achieve tomorrow and (2) tomorrow morning,
surprise surprise, everything is ready for me! I don't need to wake up and find out
that I forgot a stupid thing like the fact that my shoes are in the washing machine.
The rules are pretty easy: de-couple planning from performing and make sure everything
you need for those actions are visible and available for the time you'll need them.
</p>
        <p>
          <br />
Although it seems like planning is more tedious than actually doing the task, planning
for the <strong>future</strong> is quite relaxing. Try it: plan your tomorrow at the
end of today, think about what should be set so your tomorrow will go smoothly. It
will make it easier for you to come in the morning and simply perform, without the
burden of planning fast to perform now:
</p>
        <p>
"hhmmm... alright, it's Wednesday, what should I do today... gosh, so many things
to complete! Maybe I'll start with sending those emails... naaa.. don't have power
for that now.. maybe I'll finish that task I promised yesterday! naa.. she don't need
it for today anyway... crap! I don't have the energy to deal with it! alright, first
thing is to grab a cup of coffee".
</p>
        <p>
This leads to "do what I like best first" syndrome.
</p>
        <p>
          <br />
At the end of the day, before going home, go over the things you've accomplished and
try to see what is left for tomorrow. Relax, you don't need to do those chores now.
Write everything you should accomplish for tomorrow down (with time estimations) and
go home smiling, knowing that your tomorrow is best planned for achievements rather
than for your personal whims. 
</p>
        <img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=c5f0ef03-0a94-44b2-ada3-0b09c43f5a97" />
      </body>
      <title>Driven by Self Organization</title>
      <guid isPermaLink="false">http://www.lnbogen.com/PermaLink,guid,c5f0ef03-0a94-44b2-ada3-0b09c43f5a97.aspx</guid>
      <link>http://www.lnbogen.com/2008/09/30/DrivenBySelfOrganization.aspx</link>
      <pubDate>Tue, 30 Sep 2008 15:12:18 GMT</pubDate>
      <description>&lt;p&gt;
Think about a young fellow, wanting to get into shape. Here are 2 scenarios of how
one can tackle that wish:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;1.&lt;/strong&gt; Create a plan and "manage yourself" to keep it. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp; 20:00 - set the clock to 06:00&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:00 - wake up, &lt;strong&gt;make sure&lt;/strong&gt; you're not falling back to
sleep! get dressed etc&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:15 - &lt;strong&gt;make sure&lt;/strong&gt; to eat something small and drink some
water&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:35 - run 5km&lt;br&gt;
&amp;nbsp;&amp;nbsp; 08:00 - &lt;strong&gt;make sure&lt;/strong&gt; your bag is ready for school&lt;br&gt;
&amp;nbsp;&amp;nbsp; 08:15 - go to school&lt;br&gt;
&amp;nbsp;&amp;nbsp; ... 
&lt;br&gt;
&amp;nbsp;&amp;nbsp; 20:00 - set the clock to 06:00
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;
&lt;br&gt;
2.&lt;/strong&gt; Organize things to drive your day:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp; 20:00 - put your shoes next to your bed, set your clock to 06:00 and
set it FAR from the bed, prepare a little something to eat for tomorrow morning, prepare
your bag for (tomorrow's) school.&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:00 - wake up - go close the damn clock (you need to stand in order
to do it), get dressed etc.&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:15 - eat something small and drink some water&lt;br&gt;
&amp;nbsp;&amp;nbsp; 06:35 - run 5km&lt;br&gt;
&amp;nbsp;&amp;nbsp; 08:00 - relax for a few minutes and then go to school&lt;br&gt;
&amp;nbsp;&amp;nbsp; ... 
&lt;br&gt;
&amp;nbsp;&amp;nbsp; 20:00 - put your shoes next to your bed, set your clock to 06:00 and
set it FAR from the bed, prepare a little something to eat for tomorrow morning, prepare
your bag for (tomorrow's) school.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;strong&gt;Where most of us fail?&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I might be wrong, but it seems that a lot of us (myself included) simply can't manage
our time wisely during the day, &lt;strong&gt;for long period of time&lt;/strong&gt;. It's too
easy to forget something to do TODAY when you had to force yourself to plan it TODAY.
It's too easy to fail. It's too easy to stop the rhythm. 
&lt;br&gt;
&lt;br&gt;
This is why most of us can't lose weight, can't get into shape, can't read 5 books
every month etc. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;
&lt;br&gt;
Driven by Self-organization&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
To me, it means that I want to set &lt;strong&gt;my environment&lt;/strong&gt; to drive me into
success. If I'll take the time to prepare my tomorrow, little chance I'll fail due
to laziness: (1) I'm planning for TOMORROW, so what do I care to invest the time?
I only plan things and set the environment / mood. I don't need to run the 5km now,
I only want to make sure it will be easier to achieve tomorrow and (2) tomorrow morning,
surprise surprise, everything is ready for me! I don't need to wake up and find out
that I forgot a stupid thing like the fact that my shoes are in the washing machine.
The rules are pretty easy: de-couple planning from performing and make sure everything
you need for those actions are visible and available for the time you'll need them.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Although it seems like planning is more tedious than actually doing the task, planning
for the &lt;strong&gt;future&lt;/strong&gt; is quite relaxing. Try it: plan your tomorrow at the
end of today, think about what should be set so your tomorrow will go smoothly. It
will make it easier for you to come in the morning and simply perform, without the
burden of planning fast to perform now:
&lt;/p&gt;
&lt;p&gt;
"hhmmm... alright, it's Wednesday, what should I do today... gosh, so many things
to complete! Maybe I'll start with sending those emails... naaa.. don't have power
for that now.. maybe I'll finish that task I promised yesterday! naa.. she don't need
it for today anyway... crap! I don't have the energy to deal with it! alright, first
thing is to grab a cup of coffee".
&lt;/p&gt;
&lt;p&gt;
This leads to "do what I like best first" syndrome.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
At the end of the day, before going home, go over the things you've accomplished and
try to see what is left for tomorrow. Relax, you don't need to do those chores now.
Write everything you should accomplish for tomorrow down (with time estimations) and
go home smiling, knowing that your tomorrow is best planned for achievements rather
than for your personal whims. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.lnbogen.com/aggbug.ashx?id=c5f0ef03-0a94-44b2-ada3-0b09c43f5a97" /&gt;</description>
      <comments>http://www.lnbogen.com/CommentView,guid,c5f0ef03-0a94-44b2-ada3-0b09c43f5a97.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.lnbogen.com/Trackback.aspx?guid=b60e51a0-8158-4292-9aa1-b7a4e3ed2a94</trackback:ping>
      <pingback:server>http://www.lnbogen.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.lnbogen.com/PermaLink,guid,b60e51a0-8158-4292-9aa1-b7a4e3ed2a94.aspx</pingback:target>
      <dc:creator>Oren Ellenbogen</dc:creator>
      <wfw:comment>http://www.lnbogen.com/CommentView,guid,b60e51a0-8158-4292-9aa1-b7a4e3ed2a94.aspx</wfw:comment>
      <wfw:commentRss>http://www.lnbogen.com/SyndicationService.asmx/G