Fixed #23157 -- Improved file upload performance when many duplicate names exist

Storage.get_available_name() handled conflicts by exhaustively testing
each alternative name, starting at one until a free name was found.

In some scenarios this would lead to pathological performance due to
stat()ing many files, potentially causing I/O and reducing cache
effectiveness by warming the metadata of previously cold files.

This preserves the existing name scheme (incrementing integers), but
uses bisection to find a free name. Given a name that is duplicated
10,000 times, the number of exists() calls is reduced from 10,000 to 24.

    ['highest', None, 'got', 0, 'num stats', 1]
    ['highest', 0, 'got', 1, 'num stats', 6]
    ['highest', 1, 'got', 2, 'num stats', 6]
    ['highest', 2, 'got', 3, 'num stats', 6]
    ['highest', 3, 'got', 4, 'num stats', 6]
    ['highest', 4, 'got', 5, 'num stats', 6]
    ['highest', 5, 'got', 6, 'num stats', 6]
    ['highest', 6, 'got', 7, 'num stats', 6]
    ['highest', 7, 'got', 8, 'num stats', 6]
    ['highest', 8, 'got', 9, 'num stats', 6]
    ['highest', 9, 'got', 10, 'num stats', 6]
    ['highest', 10, 'got', 11, 'num stats', 7]
    ['highest', 100, 'got', 101, 'num stats', 12]
    ['highest', 1000, 'got', 1001, 'num stats', 18]
    ['highest', 10000, 'got', 10001, 'num stats', 24]
    ['highest', 100000, 'got', 100001, 'num stats', 32]
    ['highest', 1000000, 'got', 1000001, 'num stats', 38]
    ['highest', 10000000, 'got', 10000001, 'num stats', 44]

It is compatible with the old approach, except that if random parts of
the range are freed through deletion, previously the lowest index would
always be picked, while this approach will only repopulate indices
falling on a bisection midpoint. It doesn't seem possible to emulate the
old approach without calling either listdir() or repeatedly calling
exists() as before.

Ideally Django would use some randomized scheme, although this might be
a surprising change for existing installs. Time-based names are another
option but could still potentially break larger installs.