<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>core.async Buffering Behavior</title>
<!-- 2016-03-20 Sun 21:20 -->
<meta  http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta  name="generator" content="Org-mode" />
<meta  name="author" content="[[https://github.com/hiredman]]" />
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center; }
  .todo   { font-family: monospace; color: red; }
  .done   { color: green; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .center { margin-left: auto; margin-right: auto; text-align: center; }
  .underline { text-decoration: underline; }
  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  p.verse { margin-left: 3%; }
  pre {
    border: 1px solid #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  pre.src-sh:before    { content: 'sh'; }
  pre.src-bash:before  { content: 'sh'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-R:before     { content: 'R'; }
  pre.src-perl:before  { content: 'Perl'; }
  pre.src-java:before  { content: 'Java'; }
  pre.src-sql:before   { content: 'SQL'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.right  { text-align: center;  }
  th.left   { text-align: center;   }
  th.center { text-align: center; }
  td.right  { text-align: right;  }
  td.left   { text-align: left;   }
  td.center { text-align: center; }
  dt { font-weight: bold; }
  .footpara:nth-child(2) { display: inline; }
  .footpara { display: block; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .inlinetask {
    padding: 10px;
    border: 2px solid gray;
    margin: 10px;
    background: #ffffcc;
  }
  #org-div-home-and-up
   { text-align: right; font-size: 70%; white-space: nowrap; }
  textarea { overflow-x: auto; }
  .linenr { font-size: smaller }
  .code-highlighted { background-color: #ffff00; }
  .org-info-js_info-navigation { border-style: none; }
  #org-info-js_console-label
    { font-size: 10px; font-weight: bold; white-space: nowrap; }
  .org-info-js_search-highlight
    { background-color: #ffff00; color: #000000; font-weight: bold; }
  /*]]>*/-->
</style>
<link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css' />
<link href='http://fonts.googleapis.com/css?family=Gentium+Basic' rel='stylesheet' type='text/css' />
<style type="text/css">body{max-width:44em;margin:auto;background:#eee;color:#333;font-size:14pt}</style>
<style type="text/css">html {font-family: 'Gentium Basic', Georgia, serif;}</style>
<style type="text/css">.src-clojure {background-color:#3f3f3f; color:#dcdccc; font-family: 'Droid Sans Mono', monospace}</style>
<style type="text/css">code {font-family: 'Droid Sans Mono', monospace; font-size:90%; font-weight:700;}</style>
<style type="text/css">table {margin:auto}</style>
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2013 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.


@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">core.async Buffering Behavior</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">1. Why is buffering important?</a></li>
<li><a href="#sec-2">2. Communication Buffering in core.async</a></li>
<li><a href="#sec-3">3. Computation Buffering in core.async</a></li>
<li><a href="#sec-4">4. The Pipeline Family</a></li>
<li><a href="#sec-5">5. Etc</a></li>
</ul>
</div>
</div>

<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"><span class="section-number-2">1</span> Why is buffering important?</h2>
<div class="outline-text-2" id="text-1">
<p>
For this write up I am considering buffering to be the difference
between the input to a process and the output of a process, at the
point where the process stops accepting new input. This definition
is on the rough and ready side, which should prepare you for the
nature of things to come.
</p>

<p>
Generally, any complicated system will act like a buffer when put
between two queues, because of batching behaviors, copying behaviors
etc. So as part of understanding how to compose systems with each
other you need to understand buffers.
</p>

<p>
More concretely a situation may arise where you might have a buffer
of size five in front of your logic to persist data to disk. That
buffer of size five is critical to understanding the risk of data
loss in your system.
</p>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2"><span class="section-number-2">2</span> Communication Buffering in core.async</h2>
<div class="outline-text-2" id="text-2">
<p>
Communicating in <code>core.async</code> happens over channels. Channels are
FIFO queues. When you create a channel you have the ability to
specify a buffer size, for example: <code>(async/chan 1)</code>.  This explicit
buffer is a useful way to determine when the back pressure of a full
queue should kick in.
</p>

<p>
We can write some code that measures the buffering of a channel:
</p>
<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">defn</span> <span style="color: #93E0E3;">buffer-size</span> [c]
  (<span style="color: #F0DFAF; font-weight: bold;">let</span> [accepted? (atom <span style="color: #BFEBBF;">false</span>)]
    (<span style="color: #F0DFAF; font-weight: bold;">loop</span> [i 0]
      (reset! accepted? <span style="color: #BFEBBF;">false</span>)
      (<span style="color: #7CB8BB;">async</span>/put! c (rand) (<span style="color: #F0DFAF; font-weight: bold;">fn</span> [&amp; _] (reset! accepted? <span style="color: #BFEBBF;">true</span>)))
      (<span style="color: #7CB8BB;">Thread</span>/sleep 500) <span style="color: #5F7F5F;">;; </span><span style="color: #7F9F7F;">this is a race</span>
      (<span style="color: #F0DFAF; font-weight: bold;">if</span> @accepted?
        (<span style="color: #F0DFAF; font-weight: bold;">recur</span> (inc i))
        i))))
</pre>
</div>

<p>
If we run our <code>buffer-size</code> function over a bunch of channels we can
see it guess some buffer sizes:
</p>

<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [i 5]
  (println i <span style="color: #CC9393;">" "</span> (buffer-size (<span style="color: #7CB8BB;">async</span>/chan i))))
</pre>
</div>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="right" />

<col  class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="right">actual buffer size</th>
<th scope="col" class="right">buffer-size measurement</th>
</tr>
</thead>
<tbody>
<tr>
<td class="right">0</td>
<td class="right">0</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">1</td>
</tr>

<tr>
<td class="right">2</td>
<td class="right">2</td>
</tr>

<tr>
<td class="right">3</td>
<td class="right">3</td>
</tr>

<tr>
<td class="right">4</td>
<td class="right">4</td>
</tr>
</tbody>
</table>

<p>
All very straight forward, no surprises, the buffering behavior we
get is exactly what we ask for. That would be the end of it, but
buffering arises elsewhere too.
</p>
</div>
</div>

<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3"><span class="section-number-2">3</span> Computation Buffering in core.async</h2>
<div class="outline-text-2" id="text-3">
<p>
Channels are provided for communication, what communicates over
these channels are these machines, or processes, or threads, or
whatever you want to call them. I will call them processes. Most of
these processes will be reading from a channel and writing to a
channel, and will often end up acting as a buffer between these channels.
</p>

<p>
A very simple process is just copy:
</p>
<div class="org-src-container">

<pre class="src src-clojure"><span style="color: #5F7F5F;">;; </span><span style="color: #7F9F7F;">this is almost the same implementation wise as </span>
<span style="color: #5F7F5F;">;; </span><span style="color: #7F9F7F;">core.async's builtin pipe</span>
(<span style="color: #F0DFAF; font-weight: bold;">defn</span> <span style="color: #93E0E3;">copy</span> [in out]
  (<span style="color: #7CB8BB;">async</span>/go-loop []
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [x (<span style="color: #7CB8BB;">async</span>/&lt;! in)]
      (<span style="color: #F0DFAF; font-weight: bold;">if</span> (nil? x)
        (<span style="color: #7CB8BB;">async</span>/close! out)
        (<span style="color: #F0DFAF; font-weight: bold;">do</span>
          (<span style="color: #7CB8BB;">async</span>/&gt;! out x)
          (<span style="color: #F0DFAF; font-weight: bold;">recur</span>))))))
</pre>
</div>

<p>
We can use <code>buffer-size</code> to examine the buffering behavior of this process.
</p>
<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [i 2]
  (<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [ii 2]
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [in (<span style="color: #7CB8BB;">async</span>/chan i)
          out (<span style="color: #7CB8BB;">async</span>/chan ii)]
      (copy in out)
      (println i ii (buffer-size in)))))
</pre>
</div>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="right" />

<col  class="right" />

<col  class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="right">input buffer</th>
<th scope="col" class="right">output buffer</th>
<th scope="col" class="right">buffer-size measurement</th>
</tr>
</thead>
<tbody>
<tr>
<td class="right">0</td>
<td class="right">0</td>
<td class="right">1</td>
</tr>

<tr>
<td class="right">0</td>
<td class="right">1</td>
<td class="right">2</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">0</td>
<td class="right">2</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">1</td>
<td class="right">3</td>
</tr>
</tbody>
</table>

<p>
We can model this buffering with <code>x + y + 1 = z</code> where <code>x</code> is the
input buffer size, <code>y</code> is the output buffer size, <code>z</code> is the
buffer-size measurement, and the extra one added is the buffering of
the value from the channel in the local variable <code>x</code> in the copy
process. With the current protocol for channels, I don't think it is
possible to implement a copying process without introducing extra
buffering for at least one datum. You can't get rid of the plus one.
</p>

<p>
A slightly more complicated process might be one that outputs the
sum of every two inputs:
</p>

<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">defn</span> <span style="color: #93E0E3;">sum</span> [in out]
  (<span style="color: #7CB8BB;">async</span>/go-loop []
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [a (<span style="color: #7CB8BB;">async</span>/&lt;! in)
          b (<span style="color: #7CB8BB;">async</span>/&lt;! in)]
      (<span style="color: #F0DFAF; font-weight: bold;">do</span>
        (<span style="color: #7CB8BB;">async</span>/&gt;! out (+ a b))
        (<span style="color: #F0DFAF; font-weight: bold;">recur</span>)))))
</pre>
</div>

<p>
Let's take a look at its buffer table:
</p>

<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [i 3]
  (<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [ii 3]
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [in (<span style="color: #7CB8BB;">async</span>/chan i)
          out (<span style="color: #7CB8BB;">async</span>/chan ii)]
      (sum in out)
      (println i ii (buffer-size in)))))
</pre>
</div>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="right" />

<col  class="right" />

<col  class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="right">input buffer</th>
<th scope="col" class="right">output buffer</th>
<th scope="col" class="right">buffer-size measurement</th>
</tr>
</thead>
<tbody>
<tr>
<td class="right">0</td>
<td class="right">0</td>
<td class="right">2</td>
</tr>

<tr>
<td class="right">0</td>
<td class="right">1</td>
<td class="right">4</td>
</tr>

<tr>
<td class="right">0</td>
<td class="right">2</td>
<td class="right">6</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">0</td>
<td class="right">3</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">1</td>
<td class="right">5</td>
</tr>

<tr>
<td class="right">1</td>
<td class="right">2</td>
<td class="right">7</td>
</tr>

<tr>
<td class="right">2</td>
<td class="right">0</td>
<td class="right">4</td>
</tr>

<tr>
<td class="right">2</td>
<td class="right">1</td>
<td class="right">6</td>
</tr>

<tr>
<td class="right">2</td>
<td class="right">2</td>
<td class="right">8</td>
</tr>
</tbody>
</table>


<p>
This table is much more interesting than the previous ones because
the behavior it describes seems more complex. An equation to model
this buffering would be something like <code>x + 2y + 2 = z</code>. The output
buffer <code>y</code> is effectively doubles the size, because between the input
and the output every two elements becomes one, and you have two
variables in the process so add two.
</p>

<p>
Calling this sum process a buffer is kind of hand wavy. The sum
process is consuming more than one item from the input to produce a
single output, it really is performing some calculation. But if you
stick this in the middle of a data flow you get behavior that is
sort of buffer like, even if comparing it apples to apples with
other buffers doesn't entirely make sense. I wave my hand at it
for the sake of informal reasoning.
</p>

<p>
Now lets take a look at some processes that have a good deal more
going on.
</p>
</div>
</div>

<div id="outline-container-sec-4" class="outline-2">
<h2 id="sec-4"><span class="section-number-2">4</span> The Pipeline Family</h2>
<div class="outline-text-2" id="text-4">
<p>
My interest in measuring buffering in <code>core.async</code> started with
looking at the trio of pipeline functions. The pipeline functions
create a group of worker processes taking input from a given channel
and sending output to a given channel. I think they are the most
complicated process creating functions that ship with
<code>core.async</code>. Lets wire them to <code>buffer-size</code> and see what happens.
</p>

<div class="org-src-container">

<pre class="src src-clojure">(<span style="color: #F0DFAF; font-weight: bold;">dotimes</span> [_ 5]
  (<span style="color: #F0DFAF; font-weight: bold;">let</span> [i (rand-int 100)
        ii (rand-int 100)
        iii (inc (rand-int 100))]
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [in (<span style="color: #7CB8BB;">async</span>/chan i)
          out (<span style="color: #7CB8BB;">async</span>/chan ii)]
      (<span style="color: #7CB8BB;">async</span>/pipeline iii out (map identity) in)
      (println <span style="color: #CC9393;">"pipeline"</span> i ii iii (buffer-size in)))
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [in (<span style="color: #7CB8BB;">async</span>/chan i)
          out (<span style="color: #7CB8BB;">async</span>/chan ii)]
      (<span style="color: #7CB8BB;">async</span>/pipeline-blocking iii out (map identity) in)
      (println <span style="color: #CC9393;">"pipeline-blocking"</span> i ii iii (buffer-size in)))
    (<span style="color: #F0DFAF; font-weight: bold;">let</span> [in (<span style="color: #7CB8BB;">async</span>/chan i)
          out (<span style="color: #7CB8BB;">async</span>/chan ii)]
      (<span style="color: #7CB8BB;">async</span>/pipeline-async iii out (<span style="color: #F0DFAF; font-weight: bold;">fn</span> [x o]
                                      (<span style="color: #7CB8BB;">async</span>/&gt;! o x)
                                      (<span style="color: #7CB8BB;">async</span>/close! o)) in)
      (println <span style="color: #CC9393;">"pipeline-async"</span> i ii iii (buffer-size in)))))
</pre>
</div>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="left" />

<col  class="right" />

<col  class="right" />

<col  class="right" />

<col  class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">variant</th>
<th scope="col" class="right">input buffer</th>
<th scope="col" class="right">output buffer</th>
<th scope="col" class="right">parallelism</th>
<th scope="col" class="right">buffer-size measurement</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">pipeline</td>
<td class="right">16</td>
<td class="right">74</td>
<td class="right">9</td>
<td class="right">101</td>
</tr>

<tr>
<td class="left">pipeline-blocking</td>
<td class="right">16</td>
<td class="right">74</td>
<td class="right">9</td>
<td class="right">101</td>
</tr>

<tr>
<td class="left">pipeline-async</td>
<td class="right">16</td>
<td class="right">74</td>
<td class="right">9</td>
<td class="right">27</td>
</tr>

<tr>
<td class="left">pipeline</td>
<td class="right">42</td>
<td class="right">99</td>
<td class="right">10</td>
<td class="right">153</td>
</tr>

<tr>
<td class="left">pipeline-blocking</td>
<td class="right">42</td>
<td class="right">99</td>
<td class="right">10</td>
<td class="right">153</td>
</tr>

<tr>
<td class="left">pipeline-async</td>
<td class="right">42</td>
<td class="right">99</td>
<td class="right">10</td>
<td class="right">54</td>
</tr>

<tr>
<td class="left">pipeline</td>
<td class="right">17</td>
<td class="right">28</td>
<td class="right">63</td>
<td class="right">110</td>
</tr>

<tr>
<td class="left">pipeline-blocking</td>
<td class="right">17</td>
<td class="right">28</td>
<td class="right">63</td>
<td class="right">110</td>
</tr>

<tr>
<td class="left">pipeline-async</td>
<td class="right">17</td>
<td class="right">28</td>
<td class="right">63</td>
<td class="right">82</td>
</tr>

<tr>
<td class="left">pipeline</td>
<td class="right">53</td>
<td class="right">79</td>
<td class="right">45</td>
<td class="right">179</td>
</tr>

<tr>
<td class="left">pipeline-blocking</td>
<td class="right">53</td>
<td class="right">79</td>
<td class="right">45</td>
<td class="right">179</td>
</tr>

<tr>
<td class="left">pipeline-async</td>
<td class="right">53</td>
<td class="right">79</td>
<td class="right">45</td>
<td class="right">100</td>
</tr>

<tr>
<td class="left">pipeline</td>
<td class="right">12</td>
<td class="right">9</td>
<td class="right">68</td>
<td class="right">91</td>
</tr>

<tr>
<td class="left">pipeline-blocking</td>
<td class="right">12</td>
<td class="right">9</td>
<td class="right">68</td>
<td class="right">91</td>
</tr>

<tr>
<td class="left">pipeline-async</td>
<td class="right">12</td>
<td class="right">9</td>
<td class="right">68</td>
<td class="right">82</td>
</tr>
</tbody>
</table>


<p>
<code>pipeline</code> and <code>pipeline-blocking</code> follow an equation like <code>x +
  y + p = z</code> where <code>x</code> is the input buffer size, <code>y</code> is the output
buffer size, and <code>p</code> is the parallelism.
</p>

<p>
<code>pipeline-async</code> is the odd man out (and not just in buffering
behavior). It can be modeled with <code>x + p + 2 = z</code> (<a href="http://dev.clojure.org/jira/browse/ASYNC-163">ASYNC-163</a> apropos
of that 2).
</p>

<p>
This is not a huge surprise because <code>pipeline</code> and
<code>pipeline-blocking</code> are largely the same, they only differ on how
the workers are run. <code>pipeline-async</code> differs in the kind of
function it takes, and how the results of those functions are fed to
the output. The fact that the buffering behavior of <code>pipeline-async</code>
is not tied to the size of the output buffer is kind of troubling. I
don't know of a concrete situation where that would be a problem,
but it seems like that is at least a yellow flag.
</p>
</div>
</div>

<div id="outline-container-sec-5" class="outline-2">
<h2 id="sec-5"><span class="section-number-2">5</span> Etc</h2>
<div class="outline-text-2" id="text-5">
<ul class="org-ul">
<li><a href="https://github.com/clojure/core.async/">core.async</a>
</li>
<li>these are very simplified examples
</li>
<li><a href="https://www.youtube.com/watch?v=1bNOO3xxMc0">Everything Will Flow</a>
</li>
<li><a href="https://en.wikipedia.org/wiki/Queueing_theory">https://en.wikipedia.org/wiki/Queueing_theory</a> is as good a place to find further reading as any
</li>
<li>I am looking for a remote Clojure job, my email is <a href="mailto:hiredman@thelastcitadel.com">hiredman@thelastcitadel.com</a>
</li>
<li><a href="http://ce2144dc-f7c9-4f54-8fb6-7321a4c318db.s3.amazonaws.com/reducers.html">Reductionem ad finem</a> is another thing I wrote about some Clojure
</li>
</ul>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: <a href="https://github.com/hiredman">https://github.com/hiredman</a></p>
<p class="date">Created: 2016-03-20 Sun 21:20</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.5.1 (<a href="http://orgmode.org">Org</a> mode 8.2.10)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>
