t/perf-lib: factor boilerplate out of test_perf

About half of test_perf() is boilerplate, and half is
actually related to running the perf test. Let's split it
into two functions, so that we can reuse the boilerplate in
future commits.
t/perf/aggregate: factor our percent calculations

This will let us reuse the code when we add new values to
aggregate besides times.
t/perf: add infrastructure for measuring sizes

The main objective of scripts in the perf framework is to
run "test_perf", which measures the time it takes to run
some operation. However, it can also be interesting to see
the change in the output size of certain operations.

This patch introduces test_size, which records a single
numeric output from the test and shows it in the aggregated
output (with pretty printing and relative size comparison).
t/perf: add perf tests for fetches from a bitmapped server

A server with bitmapped packs can serve a clone very
quickly. However, fetches are not necessarily made any
faster, because we spend a lot less time in object traversal
(which is what bitmaps help with) and more time finding
deltas (because we may have to throw out on-disk deltas if
the client does not have the other side).

As a first step to making this faster, this patch introduces
a new perf script to measure fetches into a repo of various
ages from a fully-bitmapped server.

We separately measure the work done by the server (in
pack-objects) and that done by the client (in index-pack).
Furthermore, we measure the size of the resulting pack.

Breaking it down like this (instead of just doing a regular
"git fetch") lets us see how much each side benefits from
any changes. And since we know the pack size, if we estimate
the network speed, then we can calculate a complete
wall-clock time for the operation.
pack-bitmap: save "have" bitmap from walk

When we do a bitmap walk, we save the result, which
represents (WANTs & ~HAVEs); i.e., every object we care
about visiting in our walk. However, we throw away the
haves bitmap, which can sometimes be useful, too. Save it
and provide an access function so code which has performed a
walk can query it.
pack-objects: reuse deltas for thin "have" objects

When we calculate the "wants" and "haves" for a pack, we
only add the objects in the boundary commits as preferred
bases. However, we know that every object reachable from the
"haves" could be a preferred base.

We probably don't want to add these to our preferred base
list, because they would clog the delta-search window.
However, there is no reason we cannot reuse an on-disk delta
against such a deep "have" base, avoiding the delta search
for that object altogether.