When the mempool fills the verbose `getrawmempool` RPC call gets really slow.  It can take minutes for >100k transactions in the mempool.

The culprit is the univalue library.  Objects are implemented as a big list, but the library checks for duplicate keys.  So inserting n key-value pairs into an object takes O(n^2).

Possible fixes:

- Improve univalue library by using linked hash maps.
- change the RPC output format of getrawmempool to use a list of objects, instead of an object of objects.  But this breaks existing code.
- hack the library to be able to skip the duplicate check.

const CBlockIndex* block = tip;
        assert(block);
        while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
            block = block->pprev;
        }
        obj.pushKV("pruneheight",        block->nHeight);
        
        bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1);
        obj.pushKV("automatic_pruning",  automatic_pruning);
        if (automatic_pruning) {
            obj.pushKV("prune_target_size",  nPruneTarget);
        }
    }
    const Consensus::Params& consensusParams = Params().GetConsensus();
    UniValue softforks(UniValue::VARR);
    UniValue bip9_softforks(UniValue::VOBJ);
    softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
    softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
    softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
    for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) {
        BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos));
    }
    obj.pushKV("softforks",             softforks);
    obj.pushKV("bip9_softforks", bip9_softforks);
    obj.pushKV("warnings", GetWarnings("statusbar"));
    return obj;
}
struct CompareBlocksByHeight
{
    bool operator()(const CBlockIndex* a, const CBlockIndex* b) const