examples: Add throughput example

Currently loads 100,000 packets into the network in batches of 100 and
measures processing time. Three groups of three runs with one to three
threads respectively were performed on a Lenovo x201s Thinkpad:

One Bootstrap thread, 100,000 packets, 100 packet batches:
    Run 1:
        Produced for 51,958,534ns
        Consumed 100000 packets
        Network processing time: 469,941,118ns

    Run 2:
        Produced for 56,609,898ns
        Consumed 100000 packets
        Network processing time: 414,238,252ns

    Run 3:
        Produced for 53,476,970ns
        Consumed 100000 packets
        Network processing time: 483,011,092ns

The mean processing time for 100,000 packets with one thread therefore
is 455,730,154ns, with a standard deviation of 29,820,457.23ns

Two Bootstrap threads, 100,000 packets, 100 packet batches:
    Run 1:
        Produced for 87,916,446ns
        Consumed 100000 packets
        Network processing time: 376,585,462ns

    Run 2:
        Produced for 65,597,130ns
        Consumed 100000 packets
        Network processing time: 387,538,173ns

    Run 3:
        Produced for 62,111,372ns
        Consumed 100000 packets
        Network processing time: 391,031,027ns

With two Bootstrap threads we see an improvement of around 70ms, with
the mean being 384,991,554ns and standard deviation 6,130,212.13ns. The
reduction is from allowing the Bootstrap and Consumer instances to be
scheduled in parallel on a separate Bootstrap thread whilst the Producer
is processing. Allocating three processing threads to the Bootstrap
instance had minimal impact on the processing time, with results
comparable to the second run. This is mostly unsurprising as the
execution of the Bootstrap job should be quite short-lived.

For interests sake, allocating two Bootstrap threads and boosting the
batch size by a factor of 10 to 1000 packets improved processing time by
approximately 30ms:

Two Bootstrap threads, 100,000 packets, 1000 packet batches:
    Run 1:
    Produced for 39,982,849ns
    Consumed 100000 packets
    Network processing time: 353,674,570ns

    Run 2:
    Produced for 38,765,602ns
    Consumed 100000 packets
    Network processing time: 359,210,680ns

    Run 3:
    Produced for 40,864,231ns
    Consumed 100000 packets
    Network processing time: 358,492,814ns

Increasing the batch size appears to stabilise the packet production
along with network processing times. The mean run time is
357,126,021ns with a standard deviation of 2,458,077.86ns
boostrap: Dynamic programming for Node jobs

Avoid instantiating Runnables for nodes that are repeatedly pushed
through the Boostrap instance.