Home | History | Annotate | Line # | Download | only in html
SCHEDULER_README.html revision 1.1.1.1.16.2
      1 <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
      2         "http://www.w3.org/TR/html4/loose.dtd">
      3 
      4 <html>
      5 
      6 <head>
      7 
      8 <title>Postfix Queue Scheduler</title>
      9 
     10 <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
     11 
     12 </head>
     13 
     14 <body>
     15 
     16 <h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
     17 Queue Scheduler</h1>
     18 
     19 <hr>
     20 
     21 <h2> Disclaimer </h2>
     22 
     23 <p> Many of the <i>transport</i>-specific configuration parameters
     24 discussed in this document will not show up in "postconf" command
     25 output before Postfix version 2.9. This limitation applies to many
     26 parameters whose name is a combination of a <a href="master.5.html">master.cf</a> service name
     27 such as "relay" and a built-in suffix such as
     28 "_destination_concurrency_limit". </p>
     29 
     30 <h2> Overview </h2>
     31 
     32 <p> The queue manager is by far the most complex part of the Postfix
     33 mail system. It schedules delivery of new mail, retries failed
     34 deliveries at specific times, and removes mail from the queue after
     35 the last delivery attempt.  There are two major classes of mechanisms
     36 that control the operation of the queue manager. </p>
     37 
     38 <p> Topics covered by this document: </p>
     39 
     40 <ul>
     41 
     42 <li> <a href="#concurrency"> Concurrency scheduling</a>, concerned
     43 with the number of concurrent deliveries to a specific destination,
     44 including decisions on when to suspend deliveries after persistent
     45 failures.
     46 
     47 <li> <a href="#jobs"> Preemptive scheduling</a>, concerned with
     48 the selection of email messages and recipients for a given destination.
     49 
     50 <li> <a href="#credits"> Credits</a>, something this document would not be
     51 complete without.
     52 
     53 </ul>
     54 
     55 <!--
     56 
     57 <p> Once started, the <a href="qmgr.8.html">qmgr(8)</a> process runs until "postfix reload"
     58 or "postfix stop".  As a persistent process, the queue manager has
     59 to meet strict requirements with respect to code correctness and
     60 robustness. Unlike non-persistent daemon processes, the queue manager
     61 cannot benefit from Postfix's process rejuvenation mechanism that
     62 limit the impact from resource leaks and other coding errors
     63 (translation: replacing a process after a short time covers up bugs
     64 before they can become a problem).  </p>
     65 
     66 -->
     67 
     68 <h2> <a name="concurrency"> Concurrency scheduling </a> </h2>
     69 
     70 <p> The following sections document the Postfix 2.5 concurrency
     71 scheduler, after a discussion of the limitations of the earlier
     72 concurrency scheduler. This is followed by results of medium-concurrency
     73 experiments, and a discussion of trade-offs between performance and
     74 robustness.  </p>
     75 
     76 <p> The material is organized as follows: </p>
     77 
     78 <ul>
     79 
     80 <li> <a href="#concurrency_drawbacks"> Drawbacks of the existing
     81 concurrency scheduler </a>
     82 
     83 <li> <a href="#concurrency_summary_2_5"> Summary of the Postfix 2.5
     84 concurrency feedback algorithm </a>
     85 
     86 <li> <a href="#dead_summary_2_5"> Summary of the Postfix 2.5 "dead
     87 destination" detection algorithm </a>
     88 
     89 <li> <a href="#pseudo_code_2_5"> Pseudocode for the Postfix 2.5
     90 concurrency scheduler </a>
     91 
     92 <li> <a href="#concurrency_results"> Results for delivery to
     93 concurrency limited servers </a>
     94 
     95 <li> <a href="#concurrency_discussion"> Discussion of concurrency
     96 limited server results </a>
     97 
     98 <li> <a href="#concurrency_limitations"> Limitations of less-than-1
     99 per delivery feedback </a>
    100 
    101 <li> <a href="#concurrency_config"> Concurrency configuration
    102 parameters </a>
    103 
    104 </ul>
    105 
    106 <h3> <a name="concurrency_drawbacks"> Drawbacks of the existing
    107 concurrency scheduler </a> </h3>
    108 
    109 <p> From the start, Postfix has used a simple but robust algorithm
    110 where the per-destination delivery concurrency is decremented by 1
    111 after delivery failed due to connection or handshake failure, and
    112 incremented by 1 otherwise.  Of course the concurrency is never
    113 allowed to exceed the maximum per-destination concurrency limit.
    114 And when a destination's concurrency level drops to zero, the
    115 destination is declared "dead" and delivery is suspended.  </p>
    116 
    117 <p> Drawbacks of +/-1 concurrency feedback per delivery are: <p>
    118 
    119 <ul>
    120 
    121 <li> <p> Overshoot due to exponential delivery concurrency growth
    122 with each pseudo-cohort(*). This can be an issue with high-concurrency
    123 channels. For example, with the default initial concurrency of 5,
    124 concurrency would proceed over time as (5-10-20).  </p>
    125 
    126 <li> <p> Throttling down to zero concurrency after a single
    127 pseudo-cohort(*) failure. This was especially an issue with
    128 low-concurrency channels where a single failure could be sufficient
    129 to mark a destination as "dead", causing the suspension of further
    130 deliveries to the affected destination. </p>
    131 
    132 </ul>
    133 
    134 <p> (*) A pseudo-cohort is a number of delivery requests equal to
    135 a destination's delivery concurrency. </p>
    136 
    137 <p> The revised concurrency scheduler has a highly modular structure.
    138 It uses separate mechanisms for per-destination concurrency control
    139 and for "dead destination" detection.  The concurrency control in
    140 turn is built from two separate mechanisms: it supports less-than-1
    141 feedback per delivery to allow for more gradual concurrency
    142 adjustments, and it uses feedback hysteresis to suppress concurrency
    143 oscillations.  And instead of waiting for delivery concurrency to
    144 throttle down to zero, a destination is declared "dead" after a
    145 configurable number of pseudo-cohorts reports connection or handshake
    146 failure.  </p>
    147 
    148 <h3> <a name="concurrency_summary_2_5"> Summary of the Postfix 2.5
    149 concurrency feedback algorithm </a> </h3>
    150 
    151 <p> We want to increment a destination's delivery concurrency when
    152 some (not necessarily consecutive) number of deliveries complete
    153 without connection or handshake failure.  This is implemented with
    154 positive feedback g(N) where N is the destination's delivery
    155 concurrency.  With g(N)=1 feedback per delivery, concurrency increases
    156 by 1 after each positive feedback event; this gives us the old
    157 scheduler's exponential growth in time. With g(N)=1/N feedback per
    158 delivery, concurrency increases by 1 after an entire pseudo-cohort
    159 N of positive feedback reports; this gives us linear growth in time.
    160 Less-than-1 feedback per delivery and integer truncation naturally
    161 give us hysteresis, so that transitions to larger concurrency happen
    162 every 1/g(N) positive feedback events.  </p>
    163 
    164 <p> We want to decrement a destination's delivery concurrency when
    165 some (not necessarily consecutive) number of deliveries complete
    166 after connection or handshake failure.  This is implemented with
    167 negative feedback f(N) where N is the destination's delivery
    168 concurrency.  With f(N)=1 feedback per delivery, concurrency decreases
    169 by 1 after each negative feedback event; this gives us the old
    170 scheduler's behavior where concurrency is throttled down dramatically
    171 after a single pseudo-cohort failure.  With f(N)=1/N feedback per
    172 delivery, concurrency backs off more gently.  Again, less-than-1
    173 feedback per delivery and integer truncation naturally give us
    174 hysteresis, so that transitions to lower concurrency happen every
    175 1/f(N) negative feedback events.  </p>
    176 
    177 <p> However, with negative feedback we introduce a subtle twist.
    178 We "reverse" the negative hysteresis cycle so that the transition
    179 to lower concurrency happens at the <b>beginning</b> of a sequence
    180 of 1/f(N) negative feedback events.  Otherwise, a correction for
    181 overload would be made too late.  This makes the choice of f(N)
    182 relatively unimportant, as borne out by measurements later in this
    183 document.  </p>
    184 
    185 <p> In summary, the main ingredients for the Postfix 2.5 concurrency
    186 feedback algorithm are a) the option of less-than-1 positive feedback
    187 per delivery to avoid overwhelming servers, b) the option of
    188 less-than-1 negative feedback per delivery to avoid giving up too
    189 fast, c) feedback hysteresis to avoid rapid oscillation, and d) a
    190 "reverse" hysteresis cycle for negative feedback, so that it can
    191 correct for overload quickly.  </p>
    192 
    193 <h3> <a name="dead_summary_2_5"> Summary of the Postfix 2.5 "dead destination" detection algorithm </a> </h3>
    194 
    195 <p> We want to suspend deliveries to a specific destination after
    196 some number of deliveries suffers connection or handshake failure.
    197 The old scheduler declares a destination "dead" when negative (-1)
    198 feedback throttles the delivery concurrency down to zero. With
    199 less-than-1 feedback per delivery, this throttling down would
    200 obviously take too long.  We therefore have to separate "dead
    201 destination" detection from concurrency feedback.  This is implemented
    202 by introducing the concept of pseudo-cohort failure. The Postfix
    203 2.5 concurrency scheduler declares a destination "dead" after a
    204 configurable number of pseudo-cohorts suffers from connection or
    205 handshake failures. The old scheduler corresponds to the special
    206 case where the pseudo-cohort failure limit is equal to 1.  </p>
    207 
    208 <h3> <a name="pseudo_code_2_5"> Pseudocode for the Postfix 2.5 concurrency scheduler </a> </h3>
    209 
    210 <p> The pseudo code shows how the ideas behind new concurrency
    211 scheduler are implemented as of November 2007.  The actual code can
    212 be found in the module qmgr/qmgr_queue.c.  </p>
    213 
    214 <pre>
    215 Types:
    216         Each destination has one set of the following variables
    217         int concurrency
    218         double success
    219         double failure
    220         double fail_cohorts
    221 
    222 Feedback functions:
    223         N is concurrency; x, y are arbitrary numbers in [0..1] inclusive
    224         positive feedback: g(N) = x/N | x/sqrt(N) | x
    225         negative feedback: f(N) = y/N | y/sqrt(N) | y
    226 
    227 Initialization:
    228         concurrency = initial_concurrency
    229         success = 0
    230         failure = 0
    231         fail_cohorts = 0
    232 
    233 After success:
    234         fail_cohorts = 0
    235         Be prepared for feedback &gt; hysteresis, or rounding error
    236         success += g(concurrency)
    237         while (success >= 1)            Hysteresis 1
    238             concurrency += 1            Hysteresis 1
    239             failure = 0
    240             success -= 1                Hysteresis 1
    241         Be prepared for overshoot
    242         if (concurrency &gt; concurrency limit)
    243             concurrency = concurrency limit
    244 
    245 Safety:
    246         Don't apply positive feedback unless
    247             concurrency &lt; busy_refcount + init_dest_concurrency
    248         otherwise negative feedback effect could be delayed
    249 
    250 After failure:
    251         if (concurrency &gt; 0)
    252             fail_cohorts += 1.0 / concurrency
    253             if (fail_cohorts &gt; cohort_failure_limit)
    254                 concurrency = 0
    255         if (concurrency &gt; 0)
    256             Be prepared for feedback &gt; hysteresis, rounding errors
    257             failure -= f(concurrency)
    258             while (failure &lt; 0)
    259                 concurrency -= 1        Hysteresis 1
    260                 failure += 1            Hysteresis 1
    261                 success = 0
    262             Be prepared for overshoot
    263             if (concurrency &lt; 1)
    264                 concurrency = 1
    265 </pre>
    266 
    267 <h3> <a name="concurrency_results"> Results for delivery to concurrency-limited servers </a> </h3>
    268 
    269 <p> Discussions about the concurrency scheduler redesign started
    270 early 2004, when the primary goal was to find alternatives that did
    271 not exhibit exponential growth or rapid concurrency throttling.  No
    272 code was implemented until late 2007, when the primary concern had
    273 shifted towards better handling of server concurrency limits. For
    274 this reason we measure how well the new scheduler does this
    275 job.  The table below compares mail delivery performance of the old
    276 +/-1 feedback per delivery with several less-than-1 feedback
    277 functions, for different limited-concurrency server scenarios.
    278 Measurements were done with a FreeBSD 6.2 client and with FreeBSD
    279 6.2 and various Linux servers.  </p>
    280 
    281 <p> Server configuration: </p>
    282 
    283 <ul> <li> The mail flow was slowed down with 1 second latency per
    284 recipient ("<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = sleep 1"). The purpose was
    285 to make results less dependent on hardware details, by avoiding
    286 slow-downs by queue file I/O, logging I/O, and network I/O.
    287 
    288 <li> Concurrency was limited by the server process limit
    289 ("<a href="postconf.5.html#default_process_limit">default_process_limit</a> = 5" and "<a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a>
    290 = <a href="DATABASE_README.html#types">static</a>:all"). Postfix was stopped and started after changing the
    291 process limit, because the same number is also used as the backlog
    292 argument to the listen(2) system call, and "postfix reload" does
    293 not re-issue this call.
    294 
    295 <li> Mail was discarded with "<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> = <a href="DATABASE_README.html#types">static</a>:all" and
    296 "<a href="postconf.5.html#local_transport">local_transport</a> = discard". The discard action in access maps or
    297 header/body checks
    298 could not be used as it fails to update the <a href="postconf.5.html#in_flow_delay">in_flow_delay</a> counters.
    299 
    300 </ul>
    301 
    302 <p> Client configuration: </p>
    303 
    304 <ul>
    305 
    306 <li> Queue file overhead was minimized by sending one message to a
    307 virtual alias that expanded into 2000 different remote recipients.
    308 All recipients were accounted for according to the maillog file.
    309 The <a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> setting was increased to avoid
    310 complaints from the <a href="cleanup.8.html">cleanup(8)</a> server.
    311 
    312 <li> The number of deliveries was maximized with
    313 "<a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a> = 2". A smaller limit would cause
    314 Postfix to schedule the concurrency per recipient instead of domain,
    315 which is not what we want.
    316 
    317 <li> Maximum concurrency was limited with
    318 "<a href="postconf.5.html#smtp_destination_concurrency_limit">smtp_destination_concurrency_limit</a> = 20", and
    319 <a href="postconf.5.html#initial_destination_concurrency">initial_destination_concurrency</a> was set to the same value.
    320 
    321 <li> The positive and negative concurrency feedback hysteresis was
    322 1.  Concurrency was incremented by 1 at the END of 1/feedback steps
    323 of positive feedback, and was decremented by 1 at the START of
    324 1/feedback steps of negative feedback.
    325 
    326 <li> The SMTP client used the default 30s SMTP connect timeout and
    327 300s SMTP greeting timeout.
    328 
    329 </ul>
    330 
    331 <h4> Impact of the 30s SMTP connect timeout </h4>
    332 
    333 <p> The first results are for a FreeBSD 6.2 server, where our
    334 artificially low listen(2) backlog results in a very short kernel
    335 queue for established connections. The table shows that all deferred
    336 deliveries failed due to a 30s connection timeout, and none failed
    337 due to a server greeting timeout.  This measurement simulates what
    338 happens when the server's connection queue is completely full under
    339 load, and the TCP engine drops new connections.  </p>
    340 
    341 <blockquote>
    342 
    343 <table>
    344 
    345 <tr> <th>client<br> limit</th> <th>server<br> limit</th> <th>feedback<br>
    346 style</th> <th>connection<br> caching</th> <th>percentage<br>
    347 deferred</th> <th colspan="2">client concurrency<br> average/stddev</th>
    348 <th colspan=2>timed-out in<br> connect/greeting </th> </tr>
    349 
    350 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    351 
    352 <tr><td align="center">20</td> <td align="center">5</td> <td
    353 align="center">1/N</td> <td align="center">no</td> <td
    354 align="center">9.9</td> <td align="center">19.4</td> <td
    355 align="center">0.49</td> <td align="center">198</td> <td
    356 align="center">-</td> </tr>
    357 
    358 <tr><td align="center">20</td> <td align="center">5</td> <td
    359 align="center">1/N</td> <td align="center">yes</td> <td
    360 align="center">10.3</td> <td align="center">19.4</td> <td
    361 align="center">0.49</td> <td align="center">206</td> <td
    362 align="center">-</td> </tr>
    363 
    364 <tr><td align="center">20</td> <td align="center">5</td> <td
    365 align="center">1/sqrt(N)</td> <td align="center">no</td>
    366 <td align="center">10.4</td> <td align="center">19.6</td> <td
    367 align="center">0.59</td> <td align="center">208</td> <td
    368 align="center">-</td> </tr>
    369 
    370 <tr><td align="center">20</td> <td align="center">5</td> <td
    371 align="center">1/sqrt(N)</td> <td align="center">yes</td>
    372 <td align="center">10.6</td> <td align="center">19.6</td> <td
    373 align="center">0.61</td> <td align="center">212</td> <td
    374 align="center">-</td> </tr>
    375 
    376 <tr><td align="center">20</td> <td align="center">5</td> <td
    377 align="center">1</td> <td align="center">no</td> <td
    378 align="center">10.1</td> <td align="center">19.5</td> <td
    379 align="center">1.29</td> <td align="center">202</td> <td
    380 align="center">-</td> </tr>
    381 
    382 <tr><td align="center">20</td> <td align="center">5</td> <td
    383 align="center">1</td> <td align="center">yes</td> <td
    384 align="center">10.8</td> <td align="center">19.3</td> <td
    385 align="center">1.57</td> <td align="center">216</td> <td
    386 align="center">-</td> </tr>
    387 
    388 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    389 
    390 </table>
    391 
    392 <p> A busy server with a completely full connection queue.  N is
    393 the client delivery concurrency.  Failed deliveries time out after
    394 30s without completing the TCP handshake. See text for a discussion
    395 of results. </p>
    396 
    397 </blockquote>
    398 
    399 <h4> Impact of the 300s SMTP greeting timeout </h4>
    400 
    401 <p> The next table shows results for a Fedora Core 8 server (results
    402 for RedHat 7.3 are identical). In this case, the artificially small
    403 listen(2) backlog argument does not impact our measurement.  The
    404 table shows that practically all deferred deliveries fail after the
    405 300s SMTP greeting timeout. As these timeouts were 10x longer than
    406 with the first measurement, we increased the recipient count (and
    407 thus the running time) by a factor of 10 to keep the results
    408 comparable. The deferred mail percentages are a factor 10 lower
    409 than with the first measurement, because the 1s per-recipient delay
    410 was 1/300th of the greeting timeout instead of 1/30th of the
    411 connection timeout.  </p>
    412 
    413 <blockquote>
    414 
    415 <table>
    416 
    417 <tr> <th>client<br> limit</th> <th>server<br> limit</th> <th>feedback<br>
    418 style</th> <th>connection<br> caching</th> <th>percentage<br>
    419 deferred</th> <th colspan="2">client concurrency<br> average/stddev</th>
    420 <th colspan=2>timed-out in<br> connect/greeting </th> </tr>
    421 
    422 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    423 
    424 <tr> <td align="center">20</td> <td align="center">5</td> <td
    425 align="center">1/N</td> <td align="center">no</td> <td
    426 align="center">1.16</td> <td align="center">19.8</td> <td
    427 align="center">0.37</td> <td align="center">-</td> <td
    428 align="center">230</td> </tr>
    429 
    430 <tr> <td align="center">20</td> <td align="center">5</td> <td
    431 align="center">1/N</td> <td align="center">yes</td> <td
    432 align="center">1.36</td> <td align="center">19.8</td> <td
    433 align="center">0.36</td> <td align="center">-</td> <td
    434 align="center">272</td> </tr>
    435 
    436 <tr> <td align="center">20</td> <td align="center">5</td> <td
    437 align="center">1/sqrt(N)</td> <td align="center">no</td>
    438 <td align="center">1.21</td> <td align="center">19.9</td> <td
    439 align="center">0.23</td> <td align="center">4</td> <td
    440 align="center">238</td> </tr>
    441 
    442 <tr> <td align="center">20</td> <td align="center">5</td> <td
    443 align="center">1/sqrt(N)</td> <td align="center">yes</td>
    444 <td align="center">1.36</td> <td align="center">20.0</td> <td
    445 align="center">0.23</td> <td align="center">-</td> <td
    446 align="center">272</td> </tr>
    447 
    448 <tr> <td align="center">20</td> <td align="center">5</td> <td
    449 align="center">1</td> <td align="center">no</td> <td
    450 align="center">1.18</td> <td align="center">20.0</td> <td
    451 align="center">0.16</td> <td align="center">-</td> <td
    452 align="center">236</td> </tr>
    453 
    454 <tr> <td align="center">20</td> <td align="center">5</td> <td
    455 align="center">1</td> <td align="center">yes</td> <td
    456 align="center">1.39</td> <td align="center">20.0</td> <td
    457 align="center">0.16</td> <td align="center">-</td> <td
    458 align="center">278</td> </tr>
    459 
    460 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    461 
    462 </table>
    463 
    464 <p> A busy server with a non-full connection queue.  N is the client
    465 delivery concurrency. Failed deliveries complete at the TCP level,
    466 but time out after 300s while waiting for the SMTP greeting.  See
    467 text for a discussion of results.  </p>
    468 
    469 </blockquote>
    470 
    471 <h4> Impact of active server concurrency limiter </h4>
    472 
    473 <p> The final concurrency-limited result shows what happens when
    474 SMTP connections don't time out, but are rejected immediately with
    475 the Postfix server's <a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> feature
    476 (the server replies with a 421 status and disconnects immediately).
    477 Similar results can be expected with concurrency limiting features
    478 built into other MTAs or firewalls.  For this measurement we specified
    479 a server concurrency limit and a client initial destination concurrency
    480 of 5, and a server process limit of 10; all other conditions were
    481 the same as with the first measurement. The same result would be
    482 obtained with a FreeBSD or Linux server, because the "pushing back"
    483 is done entirely by the receiving side. </p>
    484 
    485 <blockquote>
    486 
    487 <table>
    488 
    489 <tr> <th>client<br> limit</th> <th>server<br> limit</th> <th>feedback<br>
    490 style</th> <th>connection<br> caching</th> <th>percentage<br>
    491 deferred</th> <th colspan="2">client concurrency<br> average/stddev</th>
    492 <th>theoretical<br>defer rate</th> </tr>
    493 
    494 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    495 
    496 <tr> <td align="center">20</td> <td align="center">5</td> <td
    497 align="center">1/N</td> <td align="center">no</td> <td
    498 align="center">16.5</td> <td align="center">5.17</td> <td
    499 align="center">0.38</td> <td align="center">1/6</td> </tr>
    500 
    501 <tr> <td align="center">20</td> <td align="center">5</td> <td
    502 align="center">1/N</td> <td align="center">yes</td> <td
    503 align="center">16.5</td> <td align="center">5.17</td> <td
    504 align="center">0.38</td> <td align="center">1/6</td> </tr>
    505 
    506 <tr> <td align="center">20</td> <td align="center">5</td> <td
    507 align="center">1/sqrt(N)</td> <td align="center">no</td>
    508 <td align="center">24.5</td> <td align="center">5.28</td> <td
    509 align="center">0.45</td> <td align="center">1/4</td> </tr>
    510 
    511 <tr> <td align="center">20</td> <td align="center">5</td> <td
    512 align="center">1/sqrt(N)</td> <td align="center">yes</td>
    513 <td align="center">24.3</td> <td align="center">5.28</td> <td
    514 align="center">0.46</td> <td align="center">1/4</td> </tr>
    515 
    516 <tr> <td align="center">20</td> <td align="center">5</td> <td
    517 align="center">1</td> <td align="center">no</td> <td
    518 align="center">49.7</td> <td align="center">5.63</td> <td
    519 align="center">0.67</td> <td align="center">1/2</td> </tr>
    520 
    521 <tr> <td align="center">20</td> <td align="center">5</td> <td
    522 align="center">1</td> <td align="center">yes</td> <td
    523 align="center">49.7</td> <td align="center">5.68</td> <td
    524 align="center">0.70</td> <td align="center">1/2</td> </tr>
    525 
    526 <tr> <td align="center" colspan="9"> <hr> </td> </tr>
    527 
    528 </table>
    529 
    530 <p> A server with active per-client concurrency limiter that replies
    531 with 421 and disconnects.  N is the client delivery concurrency.
    532 The theoretical defer rate is 1/(1+roundup(1/feedback)).  This is
    533 always 1/2 with the fixed +/-1 feedback per delivery; with the
    534 concurrency-dependent feedback variants, the defer rate decreases
    535 with increasing concurrency. See text for a discussion of results.
    536 </p>
    537 
    538 </blockquote>
    539 
    540 <h3> <a name="concurrency_discussion"> Discussion of concurrency-limited server results </a> </h3>
    541 
    542 <p> All results in the previous sections are based on the first
    543 delivery runs only; they do not include any second etc. delivery
    544 attempts. It's also worth noting that the measurements look at
    545 steady-state behavior only. They don't show what happens when the
    546 client starts sending at a much higher or lower concurrency.
    547 </p>
    548 
    549 <p> The first two examples show that the effect of feedback
    550 is negligible when concurrency is limited due to congestion. This
    551 is because the initial concurrency is already at the client's
    552 concurrency maximum, and because there is 10-100 times more positive
    553 than negative feedback.  Under these conditions, it is no surprise
    554 that the contribution from SMTP connection caching is also negligible.
    555 </p>
    556 
    557 <p> In the last example, the old +/-1 feedback per delivery will
    558 defer 50% of the mail when confronted with an active (anvil-style)
    559 server concurrency limit, where the server hangs up immediately
    560 with a 421 status (a TCP-level RST would have the same result).
    561 Less aggressive feedback mechanisms fare better than more aggressive
    562 ones.  Concurrency-dependent feedback fares even better at higher
    563 concurrencies than shown here, but has limitations as discussed in
    564 the next section.  </p>
    565 
    566 <h3> <a name="concurrency_limitations"> Limitations of less-than-1 per delivery feedback </a> </h3>
    567 
    568 <p> Less-than-1 feedback is of interest primarily when sending large
    569 amounts of mail to destinations with active concurrency limiters
    570 (servers that reply with 421, or firewalls that send RST).  When
    571 sending small amounts of mail per destination, less-than-1 per-delivery
    572 feedback won't have a noticeable effect on the per-destination
    573 concurrency, because the number of deliveries to the same destination
    574 is too small. You might just as well use zero per-delivery feedback
    575 and stay with the initial per-destination concurrency. And when
    576 mail deliveries fail due to congestion instead of active concurrency
    577 limiters, the measurements above show that per-delivery feedback
    578 has no effect.  With large amounts of mail you might just as well
    579 use zero per-delivery feedback and start with the maximal per-destination
    580 concurrency.  </p>
    581 
    582 <p> The scheduler with less-than-1 concurrency
    583 feedback per delivery solves a problem with servers that have active
    584 concurrency limiters.  This works only because feedback is handled
    585 in a peculiar manner: positive feedback will increment the concurrency
    586 by 1 at the <b>end</b> of a sequence of events of length 1/feedback,
    587 while negative feedback will decrement concurrency by 1 at the
    588 <b>beginning</b> of such a sequence.  This is how Postfix adjusts
    589 quickly for overshoot without causing lots of mail to be deferred.
    590 Without this difference in feedback treatment, less-than-1 feedback
    591 per delivery would defer 50% of the mail, and would be no better
    592 in this respect than the old +/-1 feedback per delivery.  </p>
    593 
    594 <p> Unfortunately, the same feature that corrects quickly for
    595 concurrency overshoot also makes the scheduler more sensitive for
    596 noisy negative feedback.  The reason is that one lonely negative
    597 feedback event has the same effect as a complete sequence of length
    598 1/feedback: in both cases delivery concurrency is dropped by 1
    599 immediately.  As a worst-case scenario, consider multiple servers
    600 behind a load balancer on a single IP address, and no backup MX
    601 address.  When 1 out of K servers fails to complete the SMTP handshake
    602 or drops the connection, a scheduler with 1/N (N = concurrency)
    603 feedback stops increasing its concurrency once it reaches a concurrency
    604 level of about K,  even though the good servers behind the load
    605 balancer are perfectly capable of handling more traffic. </p>
    606 
    607 <p> This noise problem gets worse as the amount of positive feedback
    608 per delivery gets smaller.  A compromise is to use fixed less-than-1
    609 positive feedback values instead of concurrency-dependent positive
    610 feedback.  For example, to tolerate 1 of 4 bad servers in the above
    611 load balancer scenario, use positive feedback of 1/4 per "good"
    612 delivery (no connect or handshake error), and use an equal or smaller
    613 amount of negative feedback per "bad" delivery.  The downside of
    614 using concurrency-independent feedback is that some of the old +/-1
    615 feedback problems will return at large concurrencies.  Sites that
    616 must deliver mail at non-trivial per-destination concurrencies will
    617 require special configuration.  </p>
    618 
    619 <h3> <a name="concurrency_config"> Concurrency configuration parameters </a> </h3>
    620 
    621 <p> The Postfix 2.5 concurrency scheduler is controlled with the
    622 following configuration parameters, where "<i>transport</i>_foo"
    623 provides a transport-specific parameter override.  All parameter
    624 default settings are compatible with earlier Postfix versions. </p>
    625 
    626 <blockquote>
    627 
    628 <table border="0">
    629 
    630 <tr> <th> Parameter name </th> <th> Postfix version </th> <th>
    631 Description </th> </tr>
    632 
    633 <tr> <td colspan="3"> <hr> </td> </tr>
    634 
    635 <tr> <td> <a href="postconf.5.html#initial_destination_concurrency">initial_destination_concurrency</a><br>
    636 <a href="postconf.5.html#transport_initial_destination_concurrency"><i>transport</i>_initial_destination_concurrency</a> </td> <td
    637 align="center"> all<br> 2.5 </td> <td> Initial per-destination
    638 delivery concurrency </td> </tr>
    639 
    640 <tr> <td> <a href="postconf.5.html#default_destination_concurrency_limit">default_destination_concurrency_limit</a><br>
    641 <a href="postconf.5.html#transport_destination_concurrency_limit"><i>transport</i>_destination_concurrency_limit</a> </td> <td align="center">
    642 all<br> all </td> <td> Maximum per-destination delivery concurrency
    643 </td> </tr>
    644 
    645 <tr> <td> <a href="postconf.5.html#default_destination_concurrency_positive_feedback">default_destination_concurrency_positive_feedback</a><br>
    646 <a href="postconf.5.html#transport_destination_concurrency_positive_feedback"><i>transport</i>_destination_concurrency_positive_feedback</a> </td>
    647 <td align="center"> 2.5<br> 2.5 </td> <td> Per-destination positive
    648 feedback amount, per delivery that does not fail with connection
    649 or handshake failure </td> </tr>
    650 
    651 <tr> <td> <a href="postconf.5.html#default_destination_concurrency_negative_feedback">default_destination_concurrency_negative_feedback</a><br>
    652 <a href="postconf.5.html#transport_destination_concurrency_negative_feedback"><i>transport</i>_destination_concurrency_negative_feedback</a> </td>
    653 <td align="center"> 2.5<br> 2.5 </td> <td> Per-destination negative
    654 feedback amount, per delivery that fails with connection or handshake
    655 failure </td> </tr>
    656 
    657 <tr> <td> <a href="postconf.5.html#default_destination_concurrency_failed_cohort_limit">default_destination_concurrency_failed_cohort_limit</a><br>
    658 <a href="postconf.5.html#transport_destination_concurrency_failed_cohort_limit"><i>transport</i>_destination_concurrency_failed_cohort_limit</a> </td>
    659 <td align="center"> 2.5<br> 2.5 </td> <td> Number of failed
    660 pseudo-cohorts after which a destination is declared "dead" and
    661 delivery is suspended </td> </tr>
    662 
    663 <tr> <td> <a href="postconf.5.html#destination_concurrency_feedback_debug">destination_concurrency_feedback_debug</a></td> <td align="center">
    664 2.5 </td> <td> Enable verbose logging of concurrency scheduler
    665 activity </td> </tr>
    666 
    667 <tr> <td colspan="3"> <hr> </td> </tr>
    668 
    669 </table>
    670 
    671 </blockquote>
    672 
    673 <h2> <a name="jobs"> Preemptive scheduling </a> </h2>
    674 
    675 <p>
    676 
    677 The following sections describe the new queue manager and its
    678 preemptive scheduler algorithm. Note that the document was originally
    679 written to describe the changes between the new queue manager (in
    680 this text referred to as <tt>nqmgr</tt>, the name it was known by
    681 before it became the default queue manager) and the old queue manager
    682 (referred to as <tt>oqmgr</tt>). This is why it refers to <tt>oqmgr</tt>
    683 every so often.
    684 
    685 </p>
    686 
    687 <p>
    688 
    689 This document is divided into sections as follows:
    690 
    691 </p>
    692 
    693 <ul>
    694 
    695 <li> <a href="#<tt>nqmgr</tt>_structures"> The structures used by
    696 nqmgr </a>
    697 
    698 <li> <a href="#<tt>nqmgr</tt>_pickup"> What happens when nqmgr picks
    699 up the message </a> - how it is assigned to transports, jobs, peers,
    700 entries
    701 
    702 <li> <a href="#<tt>nqmgr</tt>_selection"> How the entry selection
    703 works </a>
    704 
    705 <li> <a href="#<tt>nqmgr</tt>_preemption"> How the preemption
    706 works </a> - what messages may be preempted and how and what messages
    707 are chosen to preempt them
    708 
    709 <li> <a href="#<tt>nqmgr</tt>_concurrency"> How destination concurrency
    710 limits affect the scheduling algorithm </a>
    711 
    712 <li> <a href="#<tt>nqmgr</tt>_memory"> Dealing with memory resource
    713 limits </a>
    714 
    715 </ul>
    716 
    717 <h3> <a name="<tt>nqmgr</tt>_structures"> The structures used by
    718 nqmgr </a> </h3>
    719 
    720 <p>
    721 
    722 Let's start by recapitulating the structures and terms used when
    723 referring to queue manager and how it operates. Many of these are
    724 partially described elsewhere, but it is nice to have a coherent
    725 overview in one place:
    726 
    727 </p>
    728 
    729 <ul>
    730 
    731 <li> <p> Each message structure represents one mail message which
    732 Postfix is to deliver. The message recipients specify to what
    733 destinations is the message to be delivered and what transports are
    734 going to be used for the delivery. </p>
    735 
    736 <li> <p> Each recipient entry groups a batch of recipients of one
    737 message which are all going to be delivered to the same destination
    738 (and over the same transport).
    739 </p>
    740 
    741 <li> <p> Each transport structure groups everything what is going
    742 to be delivered by delivery agents dedicated for that transport.
    743 Each transport maintains a set of queues (describing the destinations
    744 it shall talk to) and jobs (referencing the messages it shall
    745 deliver). </p>
    746 
    747 <li> <p> Each transport queue (not to be confused with the on-disk
    748 <a href="QSHAPE_README.html#active_queue">active queue</a> or <a href="QSHAPE_README.html#incoming_queue">incoming queue</a>) groups everything what is going be
    749 delivered to given destination (aka nexthop) by its transport.  Each
    750 queue belongs to one transport, so each destination may be referred
    751 to by several queues, one for each transport.  Each queue maintains
    752 a list of all recipient entries (batches of message recipients)
    753 which shall be delivered to given destination (the todo list), and
    754 a list of recipient entries already being delivered by the delivery
    755 agents (the busy list). </p>
    756 
    757 <li> <p> Each queue corresponds to multiple peer structures.  Each
    758 peer structure is like the queue structure, belonging to one transport
    759 and referencing one destination. The difference is that it lists
    760 only the recipient entries which all originate from the same message,
    761 unlike the queue structure, whose entries may originate from various
    762 messages. For messages with few recipients, there is usually just
    763 one recipient entry for each destination, resulting in one recipient
    764 entry per peer. But for large mailing list messages the recipients
    765 may need to be split to multiple recipient entries, in which case
    766 the peer structure may list many entries for single destination.
    767 </p>
    768 
    769 <li> <p> Each transport job groups everything it takes to deliver
    770 one message via its transport. Each job represents one message
    771 within the context of the transport. The job belongs to one transport
    772 and message, so each message may have multiple jobs, one for each
    773 transport. The job groups all the peer structures, which describe
    774 the destinations the job's message has to be delivered to. </p>
    775 
    776 </ul>
    777 
    778 <p>
    779 
    780 The first four structures are common to both <tt>nqmgr</tt> and
    781 <tt>oqmgr</tt>, the latter two were introduced by <tt>nqmgr</tt>.
    782 
    783 </p>
    784 
    785 <p>
    786 
    787 These terms are used extensively in the text below, feel free to
    788 look up the description above anytime you'll feel you have lost a
    789 sense what is what.
    790 
    791 </p>
    792 
    793 <h3> <a name="<tt>nqmgr</tt>_pickup"> What happens when nqmgr picks
    794 up the message </a> </h3>
    795 
    796 <p>
    797 
    798 Whenever <tt>nqmgr</tt> moves a queue file into the <a href="QSHAPE_README.html#active_queue">active queue</a>,
    799 the following happens: It reads all necessary information from the
    800 queue file as <tt>oqmgr</tt> does, and also reads as many recipients
    801 as possible - more on that later, for now let's just pretend it
    802 always reads all recipients.
    803 
    804 </p>
    805 
    806 <p>
    807 
    808 Then it resolves the recipients as <tt>oqmgr</tt> does, which
    809 means obtaining (address, nexthop, transport) triple for each
    810 recipient. For each triple, it finds the transport; if it does not
    811 exist yet, it instantiates it (unless it's dead). Within the
    812 transport, it finds the destination queue for given nexthop; if it
    813 does not exist yet, it instantiates it (unless it's dead). The
    814 triple is then bound to given destination queue. This happens in
    815 qmgr_resolve() and is basically the same as in <tt>oqmgr</tt>.
    816 
    817 </p>
    818 
    819 <p>
    820 
    821 Then for each triple which was bound to some queue (and thus
    822 transport), the program finds the job which represents the message
    823 within that transport's context; if it does not exist yet, it
    824 instantiates it. Within the job, it finds the peer which represents
    825 the bound destination queue within this jobs context; if it does
    826 not exist yet, it instantiates it.  Finally, it stores the address
    827 from the resolved triple to the recipient entry which is appended
    828 to both the queue entry list and the peer entry list. The addresses
    829 for same nexthop are batched in the entries up to recipient_concurrency
    830 limit for that transport. This happens in qmgr_assign() and apart
    831 from that it operates with job and peer structures it is basically the
    832 same as in <tt>oqmgr</tt>.
    833 
    834 </p>
    835 
    836 <p>
    837 
    838 When the job is instantiated, it is enqueued on the transport's job
    839 list based on the time its message was picked up by <tt>nqmgr</tt>.
    840 For first batch of recipients this means it is appended to the end
    841 of the job list, but the ordering of the job list by the enqueue
    842 time is important as we will see shortly.
    843 
    844 </p>
    845 
    846 <p>
    847 
    848 [Now you should have pretty good idea what is the state of the
    849 <tt>nqmgr</tt> after couple of messages was picked up, what is the
    850 relation between all those job, peer, queue and entry structures.]
    851 
    852 </p>
    853 
    854 <h3> <a name="<tt>nqmgr</tt>_selection"> How the entry selection
    855 works </a> </h3>
    856 
    857 <p>
    858 
    859 Having prepared all those above mentioned structures, the task of
    860 the <tt>nqmgr</tt>'s scheduler is to choose the recipient entries
    861 one at a time and pass them to the delivery agent for corresponding
    862 transport. Now how does this work?
    863 
    864 </p>
    865 
    866 <p>
    867 
    868 The first approximation of the new scheduling algorithm is like this:
    869 
    870 </p>
    871 
    872 <blockquote>
    873 <pre>
    874 foreach transport (round-robin-by-transport)
    875 do
    876     if transport busy continue
    877     if transport process limit reached continue
    878     foreach transport's job (in the order of the transport's job list)
    879     do
    880         foreach job's peer (round-robin-by-destination)
    881              if peer-&gt;queue-&gt;concurrency &lt; peer-&gt;queue-&gt;window
    882                  return next peer entry.
    883         done
    884     done
    885 done
    886 </pre>
    887 </blockquote>
    888 
    889 <p>
    890 
    891 Now what is the "order of the transport's job list"? As we know
    892 already, the job list is by default kept in the order the message
    893 was picked up by the <tt>nqmgr</tt>. So by default we get the
    894 top-level round-robin transport, and within each transport we get
    895 the FIFO message delivery. The round-robin of the peers by the
    896 destination is perhaps of little importance in most real-life cases
    897 (unless the recipient_concurrency limit is reached, in one job there
    898 is only one peer structure for each destination), but theoretically
    899 it makes sure that even within single jobs, destinations are treated
    900 fairly.
    901 
    902 </p>
    903 
    904 <p>
    905 
    906 [By now you should have a feeling you really know how the scheduler
    907 works, except for the preemption, under ideal conditions - that is,
    908 no recipient resource limits and no destination concurrency problems.]
    909 
    910 </p>
    911 
    912 <h3> <a name="<tt>nqmgr</tt>_preemption"> How the preemption
    913 works </a> </h3>
    914 
    915 <p>
    916 
    917 As you might perhaps expect by now, the transport's job list does
    918 not remain sorted by the job's message enqueue time all the time.
    919 The most cool thing about <tt>nqmgr</tt> is not the simple FIFO
    920 delivery, but that it is able to slip mail with little recipients
    921 past the mailing-list bulk mail.  This is what the job preemption
    922 is about - shuffling the jobs on the transport's job list to get
    923 the best message delivery rates. Now how is it achieved?
    924 
    925 </p>
    926 
    927 <p>
    928 
    929 First I have to tell you that there are in fact two job lists in
    930 each transport. One is the scheduler's job list, which the scheduler
    931 is free to play with, while the other one keeps the jobs always
    932 listed in the order of the enqueue time and is used for recipient
    933 pool management we will discuss later. For now, we will deal with
    934 the scheduler's job list only.
    935 
    936 </p>
    937 
    938 <p>
    939 
    940 So, we have the job list, which is first ordered by the time the
    941 jobs' messages were enqueued, oldest messages first, the most recently
    942 picked one at the end. For now, let's assume that there are no
    943 destination concurrency problems. Without preemption, we pick some
    944 entry of the first (oldest) job on the queue, assign it to delivery
    945 agent, pick another one from the same job, assign it again, and so
    946 on, until all the entries are used and the job is delivered. We
    947 would then move onto the next job and so on and on. Now how do we
    948 manage to sneak in some entries from the recently added jobs when
    949 the first job on the job list belongs to a message going to the
    950 mailing-list and has thousands of recipient entries?
    951 
    952 </p>
    953 
    954 <p>
    955 
    956 The <tt>nqmgr</tt>'s answer is that we can artificially "inflate"
    957 the delivery time of that first job by some constant for free - it
    958 is basically the same trick you might remember as "accumulation of
    959 potential" from the amortized complexity lessons. For example,
    960 instead of delivering the entries of the first job on the job list
    961 every time a delivery agent becomes available, we can do it only
    962 every second time. If you view the moments the delivery agent becomes
    963 available on a timeline as "delivery slots", then instead of using
    964 every delivery slot for the first job, we can use only every other
    965 slot, and still the overall delivery efficiency of the first job
    966 remains the same. So the delivery <tt>11112222</tt> becomes
    967 <tt>1.1.1.1.2.2.2.2</tt> (1 and 2 are the imaginary job numbers, .
    968 denotes the free slot). Now what do we do with free slots?
    969 
    970 </p>
    971 
    972 <p>
    973 
    974 As you might have guessed, we will use them for sneaking the mail
    975 with little recipients in. For example, if we have one four-recipient
    976 mail followed by four one recipients mail, the delivery sequence
    977 (that is, the sequence in which the jobs are assigned to the
    978 delivery slots) might look like this: <tt>12131415</tt>. Hmm, fine
    979 for sneaking in the single recipient mail, but how do we sneak in
    980 the mail with more than one recipient? Say if we have one four-recipient
    981 mail followed by two two-recipient mails?
    982 
    983 </p>
    984 
    985 <p>
    986 
    987 The simple answer would be to use delivery sequence <tt>12121313</tt>.
    988 But the problem is that this does not scale well. Imagine you have
    989 mail with thousand recipients followed by mail with hundred recipients.
    990 It is tempting to suggest the  delivery sequence like <tt>121212....</tt>,
    991 but alas! Imagine there arrives another mail with say ten recipients.
    992 But there are no free slots anymore, so it can't slip by, not even
    993 if it had just only one recipients.  It will be stuck until the
    994 hundred-recipient mail is delivered, which really sucks.
    995 
    996 </p>
    997 
    998 <p>
    999 
   1000 So, it becomes obvious that while inflating the message to get
   1001 free slots is great idea, one has to be really careful of how the
   1002 free slots are assigned, otherwise one might corner himself. So,
   1003 how does <tt>nqmgr</tt> really use the free slots?
   1004 
   1005 </p>
   1006 
   1007 <p>
   1008 
   1009 The key idea is that one does not have to generate the free slots
   1010 in a uniform way. The delivery sequence <tt>111...1</tt> is no
   1011 worse than <tt>1.1.1.1</tt>, in fact, it is even better as some
   1012 entries are in the first case selected earlier than in the second
   1013 case, and none is selected later! So it is possible to first
   1014 "accumulate" the free delivery slots and then use them all at once.
   1015 It is even possible to accumulate some, then use them, then accumulate
   1016 some more and use them again, as in <tt>11..1.1</tt> .
   1017 
   1018 </p>
   1019 
   1020 <p>
   1021 
   1022 Let's get back to the one hundred recipient example. We now know
   1023 that we could first accumulate one hundred free slots, and only
   1024 after then to preempt the first job and sneak the one hundred
   1025 recipient mail in. Applying the algorithm recursively, we see the
   1026 hundred recipient job can accumulate ten free delivery slots, and
   1027 then we could preempt it and sneak in the ten-recipient mail...
   1028 Wait wait wait! Could we? Aren't we overinflating the original one
   1029 thousand recipient mail?
   1030 
   1031 </p>
   1032 
   1033 <p>
   1034 
   1035 Well, despite it looks so at the first glance, another trick will
   1036 allow us to answer "no, we are not!". If we had said that we will
   1037 inflate the delivery time twice at maximum, and then we consider
   1038 every other slot as a free slot, then we would overinflate in case
   1039 of the recursive preemption. BUT! The trick is that if we use only
   1040 every n-th slot as a free slot for n&gt;2, there is always some worst
   1041 inflation factor which we can guarantee not to be breached, even
   1042 if we apply the algorithm recursively. To be precise, if for every
   1043 k&gt;1 normally used slots we accumulate one free delivery slot, than
   1044 the inflation factor is not worse than k/(k-1) no matter how many
   1045 recursive preemptions happen. And it's not worse than (k+1)/k if
   1046 only non-recursive preemption happens. Now, having got through the
   1047 theory and the related math, let's see how <tt>nqmgr</tt> implements
   1048 this.
   1049 
   1050 </p>
   1051 
   1052 <p>
   1053 
   1054 Each job has so called "available delivery slot" counter. Each
   1055 transport has a <a href="postconf.5.html#transport_delivery_slot_cost"><i>transport</i>_delivery_slot_cost</a> parameter, which
   1056 defaults to <a href="postconf.5.html#default_delivery_slot_cost">default_delivery_slot_cost</a> parameter which is set to 5
   1057 by default. This is the k from the paragraph above. Each time k
   1058 entries of the job are selected for delivery, this counter is
   1059 incremented by one. Once there are some slots accumulated, job which
   1060 requires no more than that number of slots to be fully delivered
   1061 can preempt this job.
   1062 
   1063 </p>
   1064 
   1065 <p>
   1066 
   1067 [Well, the truth is, the counter is incremented every time an entry
   1068 is selected and it is divided by k when it is used.
   1069 But for the understanding it's good enough to use
   1070 the above approximation of the truth.]
   1071 
   1072 </p>
   1073 
   1074 <p>
   1075 
   1076 OK, so now we know the conditions which must be satisfied so one
   1077 job can preempt another one. But what job gets preempted, how do
   1078 we choose what job preempts it if there are several valid candidates,
   1079 and when does all this exactly happen?
   1080 
   1081 </p>
   1082 
   1083 <p>
   1084 
   1085 The answer for the first part is simple. The job whose entry was
   1086 selected the last time is so called current job. Normally, it is
   1087 the first job on the scheduler's job list, but destination concurrency
   1088 limits may change this as we will see later. It is always only the
   1089 current job which may get preempted.
   1090 
   1091 </p>
   1092 
   1093 <p>
   1094 
   1095 Now for the second part. The current job has certain amount of
   1096 recipient entries, and as such may accumulate at maximum some amount
   1097 of available delivery slots. It might have already accumulated some,
   1098 and perhaps even already used some when it was preempted before
   1099 (remember a job can be preempted several times). In either case,
   1100 we know how many are accumulated and how many are left to deliver,
   1101 so we know how many it may yet accumulate at maximum. Every other
   1102 job which may be delivered by less than that number of slots is a
   1103 valid candidate for preemption. How do we choose among them?
   1104 
   1105 </p>
   1106 
   1107 <p>
   1108 
   1109 The answer is - the one with maximum enqueue_time/recipient_entry_count.
   1110 That is, the older the job is, the more we should try to deliver
   1111 it in order to get best message delivery rates. These rates are of
   1112 course subject to how many recipients the message has, therefore
   1113 the division by the recipient (entry) count. No one shall be surprised
   1114 that message with n recipients takes n times longer to deliver than
   1115 message with one recipient.
   1116 
   1117 </p>
   1118 
   1119 <p>
   1120 
   1121 Now let's recap the previous two paragraphs. Isn't it too complicated?
   1122 Why don't the candidates come only among the jobs which can be
   1123 delivered within the number of slots the current job already
   1124 accumulated? Why do we need to estimate how much it has yet to
   1125 accumulate? If you found out the answer, congratulate yourself. If
   1126 we did it this simple way, we would always choose the candidate
   1127 with least recipient entries. If there were enough single recipient
   1128 mails coming in, they would always slip by the bulk mail as soon
   1129 as possible, and the two and more recipients mail would never get
   1130 a chance, no matter how long they have been sitting around in the
   1131 job list.
   1132 
   1133 </p>
   1134 
   1135 <p>
   1136 
   1137 This candidate selection has interesting implication - that when
   1138 we choose the best candidate for preemption (this is done in
   1139 qmgr_choose_candidate()), it may happen that we may not use it for
   1140 preemption immediately. This leads to an answer to the last part
   1141 of the original question - when does the preemption happen?
   1142 
   1143 </p>
   1144 
   1145 <p>
   1146 
   1147 The preemption attempt happens every time next transport's recipient
   1148 entry is to be chosen for delivery. To avoid needless overhead, the
   1149 preemption is not attempted if the current job could never accumulate
   1150 more than <a href="postconf.5.html#transport_minimum_delivery_slots"><i>transport</i>_minimum_delivery_slots</a> (defaults to
   1151 <a href="postconf.5.html#default_minimum_delivery_slots">default_minimum_delivery_slots</a> which defaults to 3). If there is
   1152 already enough accumulated slots to preempt the current job by the
   1153 chosen best candidate, it is done immediately. This basically means
   1154 that the candidate is moved in front of the current job on the
   1155 scheduler's job list and decreasing the accumulated slot counter
   1156 by the amount used by the candidate. If there is not enough slots...
   1157 well, I could say that nothing happens and the another preemption
   1158 is attempted the next time. But that's not the complete truth.
   1159 
   1160 </p>
   1161 
   1162 <p>
   1163 
   1164 The truth is that it turns out that it is not really necessary to
   1165 wait until the jobs counter accumulates all the delivery slots in
   1166 advance. Say we have ten-recipient mail followed by two two-recipient
   1167 mails. If the preemption happened when enough delivery slot accumulate
   1168 (assuming slot cost 2), the delivery sequence becomes
   1169 <tt>11112211113311</tt>. Now what would we get if we would wait
   1170 only for 50% of the necessary slots to accumulate and we promise
   1171 we would wait for the remaining 50% later, after we get back
   1172 to the preempted job? If we use such slot loan, the delivery sequence
   1173 becomes <tt>11221111331111</tt>. As we can see, it makes it no
   1174 considerably worse for the delivery of the ten-recipient mail, but
   1175 it allows the small messages to be delivered sooner.
   1176 
   1177 </p>
   1178 
   1179 <p>
   1180 
   1181 The concept of these slot loans is where the
   1182 <a href="postconf.5.html#transport_delivery_slot_discount"><i>transport</i>_delivery_slot_discount</a> and
   1183 <a href="postconf.5.html#transport_delivery_slot_loan"><i>transport</i>_delivery_slot_loan</a> come from (they default to
   1184 <a href="postconf.5.html#default_delivery_slot_discount">default_delivery_slot_discount</a> and <a href="postconf.5.html#default_delivery_slot_loan">default_delivery_slot_loan</a>, whose
   1185 values are by default 50 and 3, respectively). The discount (resp.
   1186 loan) specifies how many percent (resp. how many slots) one "gets
   1187 in advance", when the number of slots required to deliver the best
   1188 candidate is compared with the number of slots the current slot had
   1189 accumulated so far.
   1190 
   1191 </p>
   1192 
   1193 <p>
   1194 
   1195 And it pretty much concludes this chapter.
   1196 
   1197 </p>
   1198 
   1199 <p>
   1200 
   1201 [Now you should have a feeling that you pretty much understand the
   1202 scheduler and the preemption, or at least that you will have it
   1203 after you read the last chapter couple more times. You shall clearly
   1204 see the job list and the preemption happening at its head, in ideal
   1205 delivery conditions. The feeling of understanding shall last until
   1206 you start wondering what happens if some of the jobs are blocked,
   1207 which you might eventually figure out correctly from what had been
   1208 said already. But I would be surprised if your mental image of the
   1209 scheduler's functionality is not completely shattered once you
   1210 start wondering how it works when not all recipients may be read
   1211 in-core.  More on that later.]
   1212 
   1213 </p>
   1214 
   1215 <h3> <a name="<tt>nqmgr</tt>_concurrency"> How destination concurrency
   1216 limits affect the scheduling algorithm </a> </h3>
   1217 
   1218 <p>
   1219 
   1220 The <tt>nqmgr</tt> uses the same algorithm for destination concurrency
   1221 control as <tt>oqmgr</tt>. Now what happens when the destination
   1222 limits are reached and no more entries for that destination may be
   1223 selected by the scheduler?
   1224 
   1225 </p>
   1226 
   1227 <p>
   1228 
   1229 From user's point of view it is all simple. If some of the peers
   1230 of a job can't be selected, those peers are simply skipped by the
   1231 entry selection algorithm (the pseudo-code described before) and
   1232 only the selectable ones are used. If none of the peers may be
   1233 selected, the job is declared a "blocker job". Blocker jobs are
   1234 skipped by the entry selection algorithm and they are also excluded
   1235 from the candidates for preemption of current job. Thus the scheduler
   1236 effectively behaves as if the blocker jobs didn't exist on the job
   1237 list at all. As soon as at least one of the peers of a blocker job
   1238 becomes unblocked (that is, the delivery agent handling the delivery
   1239 of the recipient entry for given destination successfully finishes),
   1240 the job's blocker status is removed and the job again participates
   1241 in all further scheduler actions normally.
   1242 
   1243 </p>
   1244 
   1245 <p>
   1246 
   1247 So the summary is that the users don't really have to be concerned
   1248 about the interaction of the destination limits and scheduling
   1249 algorithm. It works well on its own and there are no knobs they
   1250 would need to control it.
   1251 
   1252 </p>
   1253 
   1254 <p>
   1255 
   1256 From a programmer's point of view, the blocker jobs complicate the
   1257 scheduler quite a lot. Without them, the jobs on the job list would
   1258 be normally delivered in strict FIFO order. If the current job is
   1259 preempted, the job preempting it is completely delivered unless it
   1260 is preempted itself. Without blockers, the current job is thus
   1261 always either the first job on the job list, or the top of the stack
   1262 of jobs preempting the first job on the job list.
   1263 
   1264 </p>
   1265 
   1266 <p>
   1267 
   1268 The visualization of the job list and the preemption stack without
   1269 blockers would be like this:
   1270 
   1271 </p>
   1272 
   1273 <blockquote>
   1274 <pre>
   1275 first job-&gt;    1--2--3--5--6--8--...    &lt;- job list
   1276 on job list    |
   1277                4    &lt;- preemption stack
   1278                |
   1279 current job-&gt;  7
   1280 </pre>
   1281 </blockquote>
   1282 
   1283 <p>
   1284 
   1285 In the example above we see that job 1 was preempted by job 4 and
   1286 then job 4 was preempted by job 7. After job 7 is completed, remaining
   1287 entries of job 4 are selected, and once they are all selected, job
   1288 1 continues.
   1289 
   1290 </p>
   1291 
   1292 <p>
   1293 
   1294 As we see, it's all very clean and straightforward. Now how does
   1295 this change because of blockers?
   1296 
   1297 </p>
   1298 
   1299 <p>
   1300 
   1301 The answer is: a lot. Any job may become blocker job at any time,
   1302 and also become normal job again at any time. This has several
   1303 important implications:
   1304 
   1305 </p>
   1306 
   1307 <ol>
   1308 
   1309 <li> <p>
   1310 
   1311 The jobs may be completed in arbitrary order. For example, in the
   1312 example above, if the current job 7 becomes blocked, the next job
   1313 4 may complete before the job 7 becomes unblocked again. Or if both
   1314 7 and 4 are blocked, then 1 is completed, then 7 becomes unblocked
   1315 and is completed, then 2 is completed and only after that 4 becomes
   1316 unblocked and is completed... You get the idea.
   1317 
   1318 </p>
   1319 
   1320 <p>
   1321 
   1322 [Interesting side note: even when jobs are delivered out of order,
   1323 from single destination's point of view the jobs are still delivered
   1324 in the expected order (that is, FIFO unless there was some preemption
   1325 involved). This is because whenever a destination queue becomes
   1326 unblocked (the destination limit allows selection of more recipient
   1327 entries for that destination), all jobs which have peers for that
   1328 destination are unblocked at once.]
   1329 
   1330 </p>
   1331 
   1332 <li> <p>
   1333 
   1334 The idea of the preemption stack at the head of the job list is
   1335 gone.  That is, it must be possible to preempt any job on the job
   1336 list. For example, if the jobs 7, 4, 1 and 2 in the example above
   1337 become all blocked, job 3 becomes the current job. And of course
   1338 we do not want the preemption to be affected by the fact that there
   1339 are some blocked jobs or not. Therefore, if it turns out that job
   1340 3 might be preempted by job 6, the implementation shall make it
   1341 possible.
   1342 
   1343 </p>
   1344 
   1345 <li> <p>
   1346 
   1347 The idea of the linear preemption stack itself is gone. It's no
   1348 longer true that one job is always preempted by only one job at one
   1349 time (that is directly preempted, not counting the recursively
   1350 nested jobs). For example, in the example above, job 1 is directly
   1351 preempted by only job 4, and job 4 by job 7. Now assume job 7 becomes
   1352 blocked, and job 4 is being delivered. If it accumulates enough
   1353 delivery slots, it is natural that it might be preempted for example
   1354 by job 8. Now job 4 is preempted by both job 7 AND job 8 at the
   1355 same time.
   1356 
   1357 </p>
   1358 
   1359 </ol>
   1360 
   1361 <p>
   1362 
   1363 Now combine the points 2) and 3) with point 1) again and you realize
   1364 that the relations on the once linear job list became pretty
   1365 complicated. If we extend the point 3) example: jobs 7 and 8 preempt
   1366 job 4, now job 8 becomes blocked too, then job 4 completes. Tricky,
   1367 huh?
   1368 
   1369 </p>
   1370 
   1371 <p>
   1372 
   1373 If I illustrate the relations after the above mentioned examples
   1374 (but those in point 1)), the situation would look like this:
   1375 
   1376 </p>
   1377 
   1378 <blockquote>
   1379 <pre>
   1380                             v- parent
   1381 
   1382 adoptive parent -&gt;    1--2--3--5--...      &lt;- "stack" level 0
   1383                       |     |
   1384 parent gone -&gt;        ?     6              &lt;- "stack" level 1
   1385                      / \
   1386 children -&gt;         7   8   ^- child       &lt;- "stack" level 2
   1387 
   1388                       ^- siblings
   1389 </pre>
   1390 </blockquote>
   1391 
   1392 <p>
   1393 
   1394 Now how does <tt>nqmgr</tt> deal with all these complicated relations?
   1395 
   1396 </p>
   1397 
   1398 <p>
   1399 
   1400 Well, it maintains them all as described, but fortunately, all these
   1401 relations are necessary only for purposes of proper counting of
   1402 available delivery slots. For purposes of ordering the jobs for
   1403 entry selection, the original rule still applies: "the job preempting
   1404 the current job is moved in front of the current job on the job
   1405 list". So for entry selection purposes, the job relations remain
   1406 as simple as this:
   1407 
   1408 </p>
   1409 
   1410 <blockquote>
   1411 <pre>
   1412 7--8--1--2--6--3--5--..   &lt;- scheduler's job list order
   1413 </pre>
   1414 </blockquote>
   1415 
   1416 <p>
   1417 
   1418 The job list order and the preemption parent/child/siblings relations
   1419 are maintained separately. And because the selection works only
   1420 with the job list, you can happily forget about those complicated
   1421 relations unless you want to study the <tt>nqmgr</tt> sources. In
   1422 that case the text above might provide some helpful introduction
   1423 to the problem domain. Otherwise I suggest you just forget about
   1424 all this and stick with the user's point of view: the blocker jobs
   1425 are simply ignored.
   1426 
   1427 </p>
   1428 
   1429 <p>
   1430 
   1431 [By now, you should have a feeling that there is more things going
   1432 under the hood than you ever wanted to know. You decide that
   1433 forgetting about this chapter is the best you can do for the sake
   1434 of your mind's health and you basically stick with the idea how the
   1435 scheduler works in ideal conditions, when there are no blockers,
   1436 which is good enough.]
   1437 
   1438 </p>
   1439 
   1440 <h3> <a name="<tt>nqmgr</tt>_memory"> Dealing with memory resource
   1441 limits </a> </h3>
   1442 
   1443 <p>
   1444 
   1445 When discussing the <tt>nqmgr</tt> scheduler, we have so far assumed
   1446 that all recipients of all messages in the <a href="QSHAPE_README.html#active_queue">active queue</a> are completely
   1447 read into the memory. This is simply not true. There is an upper
   1448 bound on the amount of memory the <tt>nqmgr</tt> may use, and
   1449 therefore it must impose some limits on the information it may store
   1450 in the memory at any given time.
   1451 
   1452 </p>
   1453 
   1454 <p>
   1455 
   1456 First of all, not all messages may be read in-core at once. At any
   1457 time, only <a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a> messages may be read in-core
   1458 at maximum. When read into memory, the messages are picked from the
   1459 <a href="QSHAPE_README.html#incoming_queue">incoming</a> and deferred message queues and moved to the <a href="QSHAPE_README.html#active_queue">active queue</a>
   1460 (incoming having priority), so if there is more than
   1461 <a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a> messages queued in the <a href="QSHAPE_README.html#active_queue">active queue</a>, the
   1462 rest will have to wait until (some of) the messages in the active
   1463 queue are completely delivered (or deferred).
   1464 
   1465 </p>
   1466 
   1467 <p>
   1468 
   1469 Even with the limited amount of in-core messages, there is another
   1470 limit which must be imposed in order to avoid memory exhaustion.
   1471 Each message may contain huge amount of recipients (tens or hundreds
   1472 of thousands are not uncommon), so if <tt>nqmgr</tt> read all
   1473 recipients of all messages in the <a href="QSHAPE_README.html#active_queue">active queue</a>, it may easily run
   1474 out of memory. Therefore there must be some upper bound on the
   1475 amount of message recipients which are read into the memory at the
   1476 same time.
   1477 
   1478 </p>
   1479 
   1480 <p>
   1481 
   1482 Before discussing how exactly <tt>nqmgr</tt> implements the recipient
   1483 limits, let's see how the sole existence of the limits themselves
   1484 affects the <tt>nqmgr</tt> and its scheduler.
   1485 
   1486 </p>
   1487 
   1488 <p>
   1489 
   1490 The message limit is straightforward - it just limits the size of
   1491 the
   1492 lookahead the <tt>nqmgr</tt>'s scheduler has when choosing which
   1493 message can preempt the current one. Messages not in the active
   1494 queue simply are not considered at all.
   1495 
   1496 </p>
   1497 
   1498 <p>
   1499 
   1500 The recipient limit complicates more things. First of all, the
   1501 message reading code must support reading the recipients in batches,
   1502 which among other things means accessing the queue file several
   1503 times and continuing where the last recipient batch ended. This is
   1504 invoked by the scheduler whenever the current job has space for more
   1505 recipients, subject to transport's refill_limit and refill_delay parameters.
   1506 It is also done any time when all
   1507 in-core recipients of the message are dealt with (which may also
   1508 mean they were deferred) but there are still more in the queue file.
   1509 
   1510 </p>
   1511 
   1512 <p>
   1513 
   1514 The second complication is that with some recipients left unread
   1515 in the queue file, the scheduler can't operate with exact counts
   1516 of recipient entries. With unread recipients, it is not clear how
   1517 many recipient entries there will be, as they are subject to
   1518 per-destination grouping. It is not even clear to what transports
   1519 (and thus jobs) the recipients will be assigned. And with messages
   1520 coming from the <a href="QSHAPE_README.html#deferred_queue">deferred queue</a>, it is not even clear how many unread
   1521 recipients are still to be delivered. This all means that the
   1522 scheduler must use only estimates of how many recipients entries
   1523 there will be.  Fortunately, it is possible to estimate the minimum
   1524 and maximum correctly, so the scheduler can always err on the safe
   1525 side.  Obviously, the better the estimates, the better results, so
   1526 it is best when we are able to read all recipients in-core and turn
   1527 the estimates into exact counts, or at least try to read as many
   1528 as possible to make the estimates as accurate as possible.
   1529 
   1530 </p>
   1531 
   1532 <p>
   1533 
   1534 The third complication is that it is no longer true that the scheduler
   1535 is done with a job once all of its in-core recipients are delivered.
   1536 It is possible that the job will be revived later, when another
   1537 batch of recipients is read in core. It is also possible that some
   1538 jobs will be created for the first time long after the first batch
   1539 of recipients was read in core. The <tt>nqmgr</tt> code must be
   1540 ready to handle all such situations.
   1541 
   1542 </p>
   1543 
   1544 <p>
   1545 
   1546 And finally, the fourth complication is that the <tt>nqmgr</tt>
   1547 code must somehow impose the recipient limit itself. Now how does
   1548 it achieve it?
   1549 
   1550 </p>
   1551 
   1552 <p>
   1553 
   1554 Perhaps the easiest solution would be to say that each message may
   1555 have at maximum X recipients stored in-core, but such solution would
   1556 be poor for several reasons. With reasonable <a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a>
   1557 values, the X would have to be quite low to maintain reasonable
   1558 memory footprint. And with low X lots of things would not work well.
   1559 The <tt>nqmgr</tt> would have problems to use the
   1560 <a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a> efficiently. The
   1561 scheduler's preemption would be suboptimal as the recipient count
   1562 estimates would be inaccurate. The message queue file would have
   1563 to be accessed many times to read in more recipients again and
   1564 again.
   1565 
   1566 </p>
   1567 
   1568 <p>
   1569 
   1570 Therefore it seems reasonable to have a solution which does not use
   1571 a limit imposed on per-message basis, but which maintains a pool
   1572 of available recipient slots, which can be shared among all messages
   1573 in the most efficient manner. And as we do not want separate
   1574 transports to compete for resources whenever possible, it seems
   1575 appropriate to maintain such recipient pool for each transport
   1576 separately. This is the general idea, now how does it work in
   1577 practice?
   1578 
   1579 </p>
   1580 
   1581 <p>
   1582 
   1583 First we have to solve little chicken-and-egg problem. If we want
   1584 to use the per-transport recipient pools, we first need to know to
   1585 what transport(s) is the message assigned. But we will find that
   1586 out only after we read in the recipients first. So it is obvious
   1587 that we first have to read in some recipients, use them to find out
   1588 to what transports is the message to be assigned, and only after
   1589 that we can use the per-transport recipient pools.
   1590 
   1591 </p>
   1592 
   1593 <p>
   1594 
   1595 Now how many recipients shall we read for the first time? This is
   1596 what <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> and <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a>
   1597 values control. The <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> value specifies
   1598 how many recipients of each message we will read for the first time,
   1599 no matter what.  It is necessary to read at least one recipient
   1600 before we can assign the message to a transport and create the first
   1601 job. However, reading only <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> recipients
   1602 even if there are only few messages with few recipients in-core would
   1603 be wasteful. Therefore if there is less than <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a>
   1604 recipients in-core so far, the first batch of recipients may be
   1605 larger than <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> - as large as is required
   1606 to reach the <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a> limit.
   1607 
   1608 </p>
   1609 
   1610 <p>
   1611 
   1612 Once the first batch of recipients was read in core and the message
   1613 jobs were created, the size of the subsequent recipient batches (if
   1614 any - of course it's best when all recipients are read in one batch)
   1615 is based solely on the position of the message jobs on their
   1616 corresponding transports' job lists. Each transport has a pool of
   1617 <a href="postconf.5.html#transport_recipient_limit"><i>transport</i>_recipient_limit</a> recipient slots which it can
   1618 distribute among its jobs (how this is done is described later).
   1619 The subsequent recipient batch may be as large as the sum of all
   1620 recipient slots of all jobs of the message permits (plus the
   1621 <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> amount which always applies).
   1622 
   1623 </p>
   1624 
   1625 <p>
   1626 
   1627 For example, if a message has three jobs, first with 1 recipient
   1628 still in-core and 4 recipient slots, second with 5 recipient in-core
   1629 and 5 recipient slots, and third with 2 recipients in-core and 0
   1630 recipient slots, it has 1+5+2=7 recipients in-core and 4+5+0=9 jobs'
   1631 recipients slots in total. This means that we could immediately
   1632 read 2+<a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> more recipients of that message
   1633 in core.
   1634 
   1635 </p>
   1636 
   1637 <p>
   1638 
   1639 The above example illustrates several things which might be worth
   1640 mentioning explicitly: first, note that although the per-transport
   1641 slots are assigned to particular jobs, we can't guarantee that once
   1642 the next batch of recipients is read in core, that the corresponding
   1643 amounts of recipients will be assigned to those jobs. The jobs lend
   1644 its slots to the message as a whole, so it is possible that some
   1645 jobs end up sponsoring other jobs of their message. For example,
   1646 if in the example above the 2 newly read recipients were assigned
   1647 to the second job, the first job sponsored the second job with 2
   1648 slots. The second notable thing is the third job, which has more
   1649 recipients in-core than it has slots. Apart from sponsoring by other
   1650 job we just saw it can be result of the first recipient batch, which
   1651 is sponsored from global recipient pool of <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a>
   1652 recipients. It can be also sponsored from the message recipient
   1653 pool of <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> recipients.
   1654 
   1655 </p>
   1656 
   1657 <p>
   1658 
   1659 Now how does each transport distribute the recipient slots among
   1660 its jobs?  The strategy is quite simple. As most scheduler activity
   1661 happens on the head of the job list, it is our intention to make
   1662 sure that the scheduler has the best estimates of the recipient
   1663 counts for those jobs. As we mentioned above, this means that we
   1664 want to try to make sure that the messages of those jobs have all
   1665 recipients read in-core. Therefore the transport distributes the
   1666 slots "along" the job list from start to end. In this case the job
   1667 list sorted by message enqueue time is used, because it doesn't
   1668 change over time as the scheduler's job list does.
   1669 
   1670 </p>
   1671 
   1672 <p>
   1673 
   1674 More specifically, each time a job is created and appended to the
   1675 job list, it gets all unused recipient slots from its transport's
   1676 pool. It keeps them until all recipients of its message are read.
   1677 When this happens, all unused recipient slots are transferred to
   1678 the next job (which is now in fact now first such job) on the job
   1679 list which still has some recipients unread, or eventually back to
   1680 the transport pool if there is no such job. Such transfer then also
   1681 happens whenever a recipient entry of that job is delivered.
   1682 
   1683 </p>
   1684 
   1685 <p>
   1686 
   1687 There is also a scenario when a job is not appended to the end of
   1688 the job list (for example it was created as a result of second or
   1689 later recipient batch). Then it works exactly as above, except that
   1690 if it was put in front of the first unread job (that is, the job
   1691 of a message which still has some unread recipients in queue file),
   1692 that job is first forced to return all of its unused recipient slots
   1693 to the transport pool.
   1694 
   1695 </p>
   1696 
   1697 <p>
   1698 
   1699 The algorithm just described leads to the following state: The first
   1700 unread job on the job list always gets all the remaining recipient
   1701 slots of that transport (if there are any). The jobs queued before
   1702 this job are completely read (that is, all recipients of their
   1703 message were already read in core) and have at maximum as many slots
   1704 as they still have recipients in-core (the maximum is there because
   1705 of the sponsoring mentioned before) and the jobs after this job get
   1706 nothing from the transport recipient pool (unless they got something
   1707 before and then the first unread job was created and enqueued in
   1708 front of them later - in such case the also get at maximum as many
   1709 slots as they have recipients in-core).
   1710 
   1711 </p>
   1712 
   1713 <p>
   1714 
   1715 Things work fine in such state for most of the time, because the
   1716 current job is either completely read in-core or has as much recipient
   1717 slots as there are, but there is one situation which we still have
   1718 to take care of specially.  Imagine if the current job is preempted
   1719 by some unread job from the job list and there are no more recipient
   1720 slots available, so this new current job could read only batches
   1721 of <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> recipients at a time. This would
   1722 really degrade performance. For this reason, each transport has
   1723 extra pool of <a href="postconf.5.html#transport_extra_recipient_limit"><i>transport</i>_extra_recipient_limit</a> recipient
   1724 slots, dedicated exactly for this situation. Each time an unread
   1725 job preempts the current job, it gets half of the remaining recipient
   1726 slots from the normal pool and this extra pool.
   1727 
   1728 </p>
   1729 
   1730 <p>
   1731 
   1732 And that's it. It sure does sound pretty complicated, but fortunately
   1733 most people don't really have to care how exactly it works as long
   1734 as it works.  Perhaps the only important things to know for most
   1735 people are the following upper bound formulas:
   1736 
   1737 </p>
   1738 
   1739 <p>
   1740 
   1741 Each transport has at maximum
   1742 
   1743 </p>
   1744 
   1745 <blockquote>
   1746 <pre>
   1747 max(
   1748 <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> * <a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a>
   1749 + *_recipient_limit + *_extra_recipient_limit,
   1750 <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a>
   1751 )
   1752 </pre>
   1753 </blockquote>
   1754 
   1755 <p>
   1756 
   1757 recipients in core.
   1758 
   1759 </p>
   1760 
   1761 <p>
   1762 
   1763 The total amount of recipients in core is
   1764 
   1765 </p>
   1766 
   1767 <blockquote>
   1768 <pre>
   1769 max(
   1770 <a href="postconf.5.html#qmgr_message_recipient_minimum">qmgr_message_recipient_minimum</a> * <a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a>
   1771 + sum( *_recipient_limit + *_extra_recipient_limit ),
   1772 <a href="postconf.5.html#qmgr_message_recipient_limit">qmgr_message_recipient_limit</a>
   1773 )
   1774 </pre>
   1775 </blockquote>
   1776 
   1777 <p>
   1778 
   1779 where the sum is over all used transports.
   1780 
   1781 </p>
   1782 
   1783 <p>
   1784 
   1785 And this terribly complicated chapter concludes the documentation
   1786 of <tt>nqmgr</tt> scheduler.
   1787 
   1788 </p>
   1789 
   1790 <p>
   1791 
   1792 [By now you should theoretically know the <tt>nqmgr</tt> scheduler
   1793 inside out. In practice, you still hope that you will never have
   1794 to really understand the last or last two chapters completely, and
   1795 fortunately most people really won't. Understanding how the scheduler
   1796 works in ideal conditions is more than good enough for vast majority
   1797 of users.]
   1798 
   1799 </p>
   1800 
   1801 <h2> <a name="credits"> Credits </a> </h2>
   1802 
   1803 <ul>
   1804 
   1805 <li> Wietse Venema designed and implemented the initial queue manager
   1806 with per-domain FIFO scheduling, and per-delivery +/-1 concurrency
   1807 feedback.
   1808 
   1809 <li> Patrik Rak designed and implemented preemption where mail with
   1810 fewer recipients can slip past mail with more recipients in a
   1811 controlled manner, and wrote up its documentation.
   1812 
   1813 <li> Wietse Venema initiated a discussion with Patrik Rak and Victor
   1814 Duchovni on alternatives for the +/-1 feedback scheduler's aggressive
   1815 behavior. This is when K/N feedback was reviewed (N = concurrency).
   1816 The discussion ended without a good solution for both negative
   1817 feedback and dead site detection.
   1818 
   1819 <li> Victor Duchovni resumed work on concurrency feedback in the
   1820 context of concurrency-limited servers.
   1821 
   1822 <li> Wietse Venema then re-designed the concurrency scheduler in
   1823 terms of the simplest possible concepts: less-than-1 concurrency
   1824 feedback per delivery, forward and reverse concurrency feedback
   1825 hysteresis, and pseudo-cohort failure. At this same time, concurrency
   1826 feedback was separated from dead site detection.
   1827 
   1828 <li> These simplifications, and their modular implementation, helped
   1829 to develop further insights into the different roles that positive
   1830 and negative concurrency feedback play, and helped to identify some
   1831 worst-case scenarios.
   1832 
   1833 </ul>
   1834 
   1835 </body>
   1836 
   1837 </html>
   1838