ServiceRegistry's per-type and per-server indices were stored as
list[str], so each list.remove(...) call in _remove was an O(n)
linear scan. Bulk async_remove of N services sharing a type or
server therefore degraded to O(N**2) — visible at shutdown for
deployments with many entries under one _type._tcp.local.
Switch the value type to dict[str, None], which preserves insertion
order (so async_get_infos_type / async_get_infos_server still return
entries in registration order) while giving O(1) add and remove.
Also delete empty buckets once their last entry is removed so that
long-lived Zeroconf instances with churning type / server names
don't leak dict keys.