A typical caching proxy problem is port allocation to backends. We
usually have a few of them, with thousands connections to each. Upon
creation of a new connection we need to find a new unique local port for
the peer:port. This is achieved by linear search in in_pcb_lport_dest().
The closer we get to the port exhaustion the more expensive this loop is.
It needs to be executed tens thousands of times to find a port or fail.
Address the problem by adding advisory negative cache that is lazily
allocated upon first conflict. Once the cache is in action we skip trying
those ports that are already marked in the cache. During the search we
may encounter a cache allocated by other lookup. In this case the caches
are merged into one. The expectation is that under a stable heavy load we
are going to stabilize at a very low number of allocated caches, ideally
one per peer:port. The cache is a bitset of IPPORT_MAX, which makes it 8k.
Unfortunately metadata pushes allocation size to 16k UMA bucket. However,
the expectation is that we are going to have a very few allocated, thus
current decisions is to not create a separate UMA zone.