From d4d5022cfc6f1b826e4c644539a2c756a7499198 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 25 Apr 2015 08:19:57 -0700 Subject: [PATCH] Use ring buffer of set iterators instead of deque of copies in mruset --- src/mruset.h | 36 ++++++++++++++++-------------------- src/net.cpp | 6 ++++-- src/test/mruset_tests.cpp | 2 +- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/mruset.h b/src/mruset.h index 1969f419c..398aa173b 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -1,12 +1,12 @@ -// Copyright (c) 2012 The Bitcoin Core developers +// Copyright (c) 2012-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_MRUSET_H #define BITCOIN_MRUSET_H -#include #include +#include #include /** STL-like set container that only keeps the most recent N elements. */ @@ -22,11 +22,13 @@ public: protected: std::set set; - std::deque queue; - size_type nMaxSize; + std::vector order; + size_type first_used; + size_type first_unused; + const size_type nMaxSize; public: - mruset(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; } + mruset(size_type nMaxSizeIn = 1) : nMaxSize(nMaxSizeIn) { clear(); } iterator begin() const { return set.begin(); } iterator end() const { return set.end(); } size_type size() const { return set.size(); } @@ -36,7 +38,9 @@ public: void clear() { set.clear(); - queue.clear(); + order.assign(nMaxSize, set.end()); + first_used = 0; + first_unused = 0; } bool inline friend operator==(const mruset& a, const mruset& b) { return a.set == b.set; } bool inline friend operator==(const mruset& a, const std::set& b) { return a.set == b; } @@ -45,25 +49,17 @@ public: { std::pair ret = set.insert(x); if (ret.second) { - if (nMaxSize && queue.size() == nMaxSize) { - set.erase(queue.front()); - queue.pop_front(); + if (set.size() == nMaxSize + 1) { + set.erase(order[first_used]); + order[first_used] = set.end(); + if (++first_used == nMaxSize) first_used = 0; } - queue.push_back(x); + order[first_unused] = ret.first; + if (++first_unused == nMaxSize) first_unused = 0; } return ret; } size_type max_size() const { return nMaxSize; } - size_type max_size(size_type s) - { - if (s) - while (queue.size() > s) { - set.erase(queue.front()); - queue.pop_front(); - } - nMaxSize = s; - return nMaxSize; - } }; #endif // BITCOIN_MRUSET_H diff --git a/src/net.cpp b/src/net.cpp index 4648dae11..2de04fc57 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1905,7 +1905,10 @@ bool CAddrDB::Read(CAddrMan& addr) unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } -CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addrKnown(5000, 0.001, insecure_rand()) +CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : + ssSend(SER_NETWORK, INIT_PROTO_VERSION), + addrKnown(5000, 0.001, insecure_rand()), + setInventoryKnown(SendBufferSize() / 1000) { nServices = 0; hSocket = hSocketIn; @@ -1934,7 +1937,6 @@ CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fIn nStartingHeight = -1; fGetAddr = false; fRelayTxes = false; - setInventoryKnown.max_size(SendBufferSize() / 1000); pfilter = new CBloomFilter(); nPingNonceSent = 0; nPingUsecStart = 0; diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index bd4e9c1d3..9a9763e27 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -24,7 +24,7 @@ private: std::set set; public: - mrutester() { mru.max_size(MAX_SIZE); } + mrutester() : mru(MAX_SIZE) {} int size() const { return set.size(); } void insert(int n)