<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.0.12-alpha" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: Too much mail is bad for you</title>
	<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you</link>
	<description>What happens at LShift</description>
	<pubDate>Sat, 11 Oct 2008 11:51:39 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.12-alpha</generator>

	<item>
		<title>by: Pichi</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67308</link>
		<pubDate>Wed, 03 Oct 2007 15:12:08 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67308</guid>
					<description>&lt;p&gt;&lt;a href="http://pichis-blog.blogspot.com/2007/10/keep-your-mailbox-empty.html" rel="nofollow"&gt;Non blocking and fast solution&lt;/a&gt; with readable source code :-)&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p><a href="http://pichis-blog.blogspot.com/2007/10/keep-your-mailbox-empty.html" rel="nofollow">Non blocking and fast solution</a> with readable source code :-)</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Pichi</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67305</link>
		<pubDate>Wed, 03 Oct 2007 13:36:24 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67305</guid>
					<description>&lt;p&gt;Enable &#60;pre&#62; tag in comments will be good idea, I think.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Enable &lt;pre&gt; tag in comments will be good idea, I think.</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Pichi</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67304</link>
		<pubDate>Wed, 03 Oct 2007 13:34:13 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67304</guid>
					<description>&lt;p&gt;&lt;code&gt;-module(mqueue).&lt;/p&gt;

&lt;p&gt;-export([timed_run/3]).&lt;/p&gt;

&lt;p&gt;producer(0, ConsumerPid, &lt;em&gt;WithAck) -&#62;
    ConsumerPid ! {done, self()},
    receive
        done -&#62; ok
    end;
producer(N, ConsumerPid, WithAck = false) -&#62;
    ConsumerPid ! {msg, self()},
    producer(N-1, ConsumerPid, WithAck);
producer(N, ConsumerPid, WithAck = true) -&#62;
    ConsumerPid ! {acked&lt;/em&gt;msg, self()},
    receive
        ack -&#62; ok
    end,
    producer(N-1, ConsumerPid, WithAck).&lt;/p&gt;

&lt;p&gt;consumer(M, EchoPid) -&#62;
    receive
        {msg, &lt;em&gt;From} -&#62;
            call&lt;/em&gt;echo(M, EchoPid),
            consumer(M, EchoPid);
        {acked&lt;em&gt;msg, From} -&#62;
            From ! ack,
            call&lt;/em&gt;echo(M, EchoPid),
            consumer(M, EchoPid);
        {done, From} -&#62;
            EchoPid ! done,
            From ! done
    end.&lt;/p&gt;

&lt;p&gt;queue&lt;em&gt;keeper&lt;/em&gt;empty(ConsumerPid) -&#62;
    receive
        {msg, &lt;em&gt;From} -&#62;
            ConsumerPid ! {acked&lt;/em&gt;msg, self()},
            queue&lt;em&gt;keeper&lt;/em&gt;waiting(queue:new(), ConsumerPid);
        {done, From} -&#62;
            ConsumerPid ! {done, self()},
            receive
                done -&#62;
                    From ! done
            end
    end.&lt;/p&gt;

&lt;p&gt;queue&lt;em&gt;keeper&lt;/em&gt;waiting(Q, ConsumerPid) -&#62;
    receive
        {msg, &lt;em&gt;From} -&#62;
            queue&lt;/em&gt;keeper&lt;em&gt;waiting(queue:in({acked&lt;/em&gt;msg, self()}, Q), ConsumerPid);
        ack -&#62; case queue:out(Q) of
                {{value, Msg}, Q1} -&#62;
                    ConsumerPid ! Msg,
                    queue&lt;em&gt;keeper&lt;/em&gt;waiting(Q1, ConsumerPid);
                {empty, Q} -&#62; queue&lt;em&gt;keeper&lt;/em&gt;empty(ConsumerPid)
            end
    end.&lt;/p&gt;

&lt;p&gt;call&lt;em&gt;echo(0, _EchoPid) -&#62;
    ok;
call&lt;/em&gt;echo(M, EchoPid) -&#62;
    EchoPid ! {hello, self()},
    receive
        hello -&#62; call_echo(M-1, EchoPid)
    end.&lt;/p&gt;

&lt;p&gt;echo() -&#62;
    receive
        {Msg, From} -&#62;
            From ! Msg,
            echo();
        done -&#62; ok
    end.&lt;/p&gt;

&lt;p&gt;run(N, M, WithAck) -&#62;
    EchoPid     = spawn&lt;em&gt;link(fun echo/0),
    ConsumerPid = spawn&lt;/em&gt;link(
                    fun () -&#62;
                            consumer(M, EchoPid) end),
    case WithAck of
        true -&#62;
            producer(N, ConsumerPid, WithAck);
        false -&#62;
            producer(N, spawn&lt;em&gt;link(
                        fun() -&#62;
                            queue&lt;/em&gt;keeper_empty(ConsumerPid) end), WithAck)
    end.&lt;/p&gt;

&lt;p&gt;time(F) -&#62;
    Start = erlang:now(),
    F(),
    timer:now_diff(erlang:now(), Start).&lt;/p&gt;

&lt;p&gt;timed_run(N, M, WithAck) -&#62;
    time(fun() -&#62; run(N, M, WithAck) end).
&lt;/code&gt;
With own queue managing it's only about 1.25 times slower and not blocking producer.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p><code>-module(mqueue).</code></p>
<p>-export([timed_run/3]).</p>
<p>producer(0, ConsumerPid, <em>WithAck) -&gt;<br />
    ConsumerPid ! {done, self()},<br />
    receive<br />
        done -&gt; ok<br />
    end;<br />
producer(N, ConsumerPid, WithAck = false) -&gt;<br />
    ConsumerPid ! {msg, self()},<br />
    producer(N-1, ConsumerPid, WithAck);<br />
producer(N, ConsumerPid, WithAck = true) -&gt;<br />
    ConsumerPid ! {acked</em>msg, self()},<br />
    receive<br />
        ack -&gt; ok<br />
    end,<br />
    producer(N-1, ConsumerPid, WithAck).</p>
<p>consumer(M, EchoPid) -&gt;<br />
    receive<br />
        {msg, <em>From} -&gt;<br />
            call</em>echo(M, EchoPid),<br />
            consumer(M, EchoPid);<br />
        {acked<em>msg, From} -&gt;<br />
            From ! ack,<br />
            call</em>echo(M, EchoPid),<br />
            consumer(M, EchoPid);<br />
        {done, From} -&gt;<br />
            EchoPid ! done,<br />
            From ! done<br />
    end.</p>
<p>queue<em>keeper</em>empty(ConsumerPid) -&gt;<br />
    receive<br />
        {msg, <em>From} -&gt;<br />
            ConsumerPid ! {acked</em>msg, self()},<br />
            queue<em>keeper</em>waiting(queue:new(), ConsumerPid);<br />
        {done, From} -&gt;<br />
            ConsumerPid ! {done, self()},<br />
            receive<br />
                done -&gt;<br />
                    From ! done<br />
            end<br />
    end.</p>
<p>queue<em>keeper</em>waiting(Q, ConsumerPid) -&gt;<br />
    receive<br />
        {msg, <em>From} -&gt;<br />
            queue</em>keeper<em>waiting(queue:in({acked</em>msg, self()}, Q), ConsumerPid);<br />
        ack -&gt; case queue:out(Q) of<br />
                {{value, Msg}, Q1} -&gt;<br />
                    ConsumerPid ! Msg,<br />
                    queue<em>keeper</em>waiting(Q1, ConsumerPid);<br />
                {empty, Q} -&gt; queue<em>keeper</em>empty(ConsumerPid)<br />
            end<br />
    end.</p>
<p>call<em>echo(0, _EchoPid) -&gt;<br />
    ok;<br />
call</em>echo(M, EchoPid) -&gt;<br />
    EchoPid ! {hello, self()},<br />
    receive<br />
        hello -&gt; call_echo(M-1, EchoPid)<br />
    end.</p>
<p>echo() -&gt;<br />
    receive<br />
        {Msg, From} -&gt;<br />
            From ! Msg,<br />
            echo();<br />
        done -&gt; ok<br />
    end.</p>
<p>run(N, M, WithAck) -&gt;<br />
    EchoPid     = spawn<em>link(fun echo/0),<br />
    ConsumerPid = spawn</em>link(<br />
                    fun () -&gt;<br />
                            consumer(M, EchoPid) end),<br />
    case WithAck of<br />
        true -&gt;<br />
            producer(N, ConsumerPid, WithAck);<br />
        false -&gt;<br />
            producer(N, spawn<em>link(<br />
                        fun() -&gt;<br />
                            queue</em>keeper_empty(ConsumerPid) end), WithAck)<br />
    end.</p>
<p>time(F) -&gt;<br />
    Start = erlang:now(),<br />
    F(),<br />
    timer:now_diff(erlang:now(), Start).</p>
<p>timed_run(N, M, WithAck) -&gt;<br />
    time(fun() -&gt; run(N, M, WithAck) end).</p>
<p>With own queue managing it&#8217;s only about 1.25 times slower and not blocking producer.</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Daniel Kwiecinski</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67300</link>
		<pubDate>Wed, 03 Oct 2007 13:00:02 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67300</guid>
					<description>&lt;p&gt;My idea to improve the erlang's queue implementation is to make it a tree rather than list. As everything in erlang is comparable the implementation of such balanced tree should be straightforward.&lt;/p&gt;

&lt;p&gt;Cheers,
Daniel&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>My idea to improve the erlang&#8217;s queue implementation is to make it a tree rather than list. As everything in erlang is comparable the implementation of such balanced tree should be straightforward.</p>
<p>Cheers,<br />
Daniel</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: tonyg</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67260</link>
		<pubDate>Tue, 02 Oct 2007 16:57:04 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67260</guid>
					<description>&lt;p&gt;@thomas: I'm pretty sure Erlang's lists are singly-linked, like ML, lisp, scheme, Haskell etc., which would make strings singly-linked as well. This is, surprisingly, usually a pretty good way of operating. I've written a little more about some of the issues in an &lt;a href="http://www.lshift.net/blog/2007/09/13/how-should-json-strings-be-represented-in-erlang" rel="nofollow"&gt;earlier article&lt;/a&gt;, if you're interested.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>@thomas: I&#8217;m pretty sure Erlang&#8217;s lists are singly-linked, like ML, lisp, scheme, Haskell etc., which would make strings singly-linked as well. This is, surprisingly, usually a pretty good way of operating. I&#8217;ve written a little more about some of the issues in an <a href="http://www.lshift.net/blog/2007/09/13/how-should-json-strings-be-represented-in-erlang" rel="nofollow">earlier article</a>, if you&#8217;re interested.</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Vlad</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67192</link>
		<pubDate>Tue, 02 Oct 2007 08:16:01 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67192</guid>
					<description>&lt;p&gt;Hi,&lt;/p&gt;

&lt;p&gt;If the producer must send messages asynchronously, then a solution is to add a buffering process between it and the consumer. Send async messages and the buffer will make sync calls to the consumer, sending a small number of messages at a time and then waiting for ack.&lt;/p&gt;

&lt;p&gt;Of course, this works only if the messages aren' t to be selectively received.&lt;/p&gt;

&lt;p&gt;regards,
Vlad&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Hi,</p>
<p>If the producer must send messages asynchronously, then a solution is to add a buffering process between it and the consumer. Send async messages and the buffer will make sync calls to the consumer, sending a small number of messages at a time and then waiting for ack.</p>
<p>Of course, this works only if the messages aren&#8217; t to be selectively received.</p>
<p>regards,<br />
Vlad</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: matthias</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67190</link>
		<pubDate>Tue, 02 Oct 2007 07:32:35 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67190</guid>
					<description>&lt;blockquote&gt;
  &lt;p&gt;So, how did you go about solving this problem ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I made the interaction between the producer and consumer synchronous. That is not an appropriate solution in general, but in this particular case it was the easiest and correct thing to do.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<blockquote>
<p>So, how did you go about solving this problem ?</p>
</blockquote>
<p>I made the interaction between the producer and consumer synchronous. That is not an appropriate solution in general, but in this particular case it was the easiest and correct thing to do.</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: thomas figg</title>
		<link>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67167</link>
		<pubDate>Mon, 01 Oct 2007 18:55:21 +0000</pubDate>
		<guid>http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you#comment-67167</guid>
					<description>&lt;p&gt;So, how did you go about solving this problem ?&lt;/p&gt;

&lt;p&gt;Did you use an intermediate process, or did you empty the message box into a seperate list ? or .... ?&lt;/p&gt;

&lt;p&gt;Another bug-like behaviour with erlang is with regards to it's string handling (iirc as doubly linked lists with one node per character) which tripped up tim bray: &lt;/p&gt;

&lt;p&gt;http://www.tbray.org/ongoing/When/200x/2007/09/20/Wide-Finder&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>So, how did you go about solving this problem ?</p>
<p>Did you use an intermediate process, or did you empty the message box into a seperate list ? or &#8230;. ?</p>
<p>Another bug-like behaviour with erlang is with regards to it&#8217;s string handling (iirc as doubly linked lists with one node per character) which tripped up tim bray: </p>
<p>http://www.tbray.org/ongoing/When/200x/2007/09/20/Wide-Finder</p>
]]></content:encoded>
				</item>
</channel>
</rss>
