2015-08-17 18:07:47 +02:00
|
|
|
// 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.
|
|
|
|
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <limitedmap.h>
|
2015-08-17 18:07:47 +02:00
|
|
|
|
2022-02-25 18:19:25 +01:00
|
|
|
#include <test/util/setup_common.h>
|
2015-08-17 18:07:47 +02:00
|
|
|
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(limitedmap_tests, BasicTestingSetup)
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(limitedmap_test)
|
|
|
|
{
|
|
|
|
// create a limitedmap capped at 10 items
|
Collection of minor performance optimizations (#2855)
* Merge #13176: Improve CRollingBloomFilter performance: replace modulus with FastMod
9aac9f90d5e56752cc6cbfac48063ad29a01143c replace modulus with FastMod (Martin Ankerl)
Pull request description:
Not sure if this is optimization is necessary, but anyway I have some spare time so here it is. This replaces the slow modulo operation with a much faster 64bit multiplication & shift. This works when the hash is uniformly distributed between 0 and 2^32-1. This speeds up the benchmark by a factor of about 1.3:
```
RollingBloom, 5, 1500000, 3.73733, 4.97569e-07, 4.99002e-07, 4.98372e-07 # before
RollingBloom, 5, 1500000, 2.86842, 3.81630e-07, 3.83730e-07, 3.82473e-07 # FastMod
```
Be aware that this changes the internal data of the filter, so this should probably
not be used for CBloomFilter because of interoperability problems.
Tree-SHA512: 04104f3fb09f56c9d14458a6aad919aeb0a5af944e8ee6a31f00e93c753e22004648c1cd65bf36752b6addec528d19fb665c27b955ce1666a85a928e17afa47a
* Use unordered_map in CSporkManager
In one of my profiling sessions with many InstantSend transactions
happening, calls into CSporkManager added up to about 1% of total CPU time.
This is easily avoidable by using unordered maps.
* Use std::unordered_map instead of std::map in limitedmap
* Use unordered_set for CNode::setAskFor
* Add serialization support for unordered maps and sets
* Use unordered_map for mapArgs and mapMultiArgs
* Let limitedmap prune in batches and use unordered_multimap
Due to the batched pruning, there is no need to maintain an ordered map
of values anymore. Only when nPruneAfterSize, there is a need to create
a temporary ordered vector of values to figure out what can be removed.
* Instead of using a multimap for mapAskFor, use a vector which we sort on demand
CNode::AskFor will now push entries into an initially unordered vector
instead of an ordered multimap. Only when we later want to use vecAskFor in
SendMessages, we sort the vector.
The vector will actually be mostly sorted in most cases as insertion order
usually mimics the desired ordering. Only the last few entries might need
some shuffling around. Doing the sort on-demand should be less wasteful
then trying to maintain correct order all the time.
* Fix compilation of tests
* Fix limitedmap tests
* Rename limitedmap to unordered_limitedmap to ensure backports conflict
This ensures that future backports that depends on limitedmap's ordering
conflict so that we are made aware of needed action.
* Fix compilation error on Travis
2019-04-11 14:42:14 +02:00
|
|
|
unordered_limitedmap<int, int> map(10);
|
2015-08-17 18:07:47 +02:00
|
|
|
|
|
|
|
// check that the max size is 10
|
|
|
|
BOOST_CHECK(map.max_size() == 10);
|
|
|
|
|
|
|
|
// check that it's empty
|
|
|
|
BOOST_CHECK(map.size() == 0);
|
|
|
|
|
|
|
|
// insert (-1, -1)
|
|
|
|
map.insert(std::pair<int, int>(-1, -1));
|
|
|
|
|
|
|
|
// make sure that the size is updated
|
|
|
|
BOOST_CHECK(map.size() == 1);
|
|
|
|
|
2017-01-22 13:28:14 +01:00
|
|
|
// make sure that the new item is in the map
|
2015-08-17 18:07:47 +02:00
|
|
|
BOOST_CHECK(map.count(-1) == 1);
|
|
|
|
|
|
|
|
// insert 10 new items
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
map.insert(std::pair<int, int>(i, i + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure that the map now contains 10 items...
|
|
|
|
BOOST_CHECK(map.size() == 10);
|
|
|
|
|
|
|
|
// ...and that the first item has been discarded
|
|
|
|
BOOST_CHECK(map.count(-1) == 0);
|
|
|
|
|
|
|
|
// iterate over the map, both with an index and an iterator
|
Collection of minor performance optimizations (#2855)
* Merge #13176: Improve CRollingBloomFilter performance: replace modulus with FastMod
9aac9f90d5e56752cc6cbfac48063ad29a01143c replace modulus with FastMod (Martin Ankerl)
Pull request description:
Not sure if this is optimization is necessary, but anyway I have some spare time so here it is. This replaces the slow modulo operation with a much faster 64bit multiplication & shift. This works when the hash is uniformly distributed between 0 and 2^32-1. This speeds up the benchmark by a factor of about 1.3:
```
RollingBloom, 5, 1500000, 3.73733, 4.97569e-07, 4.99002e-07, 4.98372e-07 # before
RollingBloom, 5, 1500000, 2.86842, 3.81630e-07, 3.83730e-07, 3.82473e-07 # FastMod
```
Be aware that this changes the internal data of the filter, so this should probably
not be used for CBloomFilter because of interoperability problems.
Tree-SHA512: 04104f3fb09f56c9d14458a6aad919aeb0a5af944e8ee6a31f00e93c753e22004648c1cd65bf36752b6addec528d19fb665c27b955ce1666a85a928e17afa47a
* Use unordered_map in CSporkManager
In one of my profiling sessions with many InstantSend transactions
happening, calls into CSporkManager added up to about 1% of total CPU time.
This is easily avoidable by using unordered maps.
* Use std::unordered_map instead of std::map in limitedmap
* Use unordered_set for CNode::setAskFor
* Add serialization support for unordered maps and sets
* Use unordered_map for mapArgs and mapMultiArgs
* Let limitedmap prune in batches and use unordered_multimap
Due to the batched pruning, there is no need to maintain an ordered map
of values anymore. Only when nPruneAfterSize, there is a need to create
a temporary ordered vector of values to figure out what can be removed.
* Instead of using a multimap for mapAskFor, use a vector which we sort on demand
CNode::AskFor will now push entries into an initially unordered vector
instead of an ordered multimap. Only when we later want to use vecAskFor in
SendMessages, we sort the vector.
The vector will actually be mostly sorted in most cases as insertion order
usually mimics the desired ordering. Only the last few entries might need
some shuffling around. Doing the sort on-demand should be less wasteful
then trying to maintain correct order all the time.
* Fix compilation of tests
* Fix limitedmap tests
* Rename limitedmap to unordered_limitedmap to ensure backports conflict
This ensures that future backports that depends on limitedmap's ordering
conflict so that we are made aware of needed action.
* Fix compilation error on Travis
2019-04-11 14:42:14 +02:00
|
|
|
unordered_limitedmap<int, int>::const_iterator it = map.begin();
|
2015-08-17 18:07:47 +02:00
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
// make sure the item is present
|
|
|
|
BOOST_CHECK(map.count(i) == 1);
|
|
|
|
|
2016-11-29 11:12:39 +01:00
|
|
|
// use the iterator to check for the expected key and value
|
Collection of minor performance optimizations (#2855)
* Merge #13176: Improve CRollingBloomFilter performance: replace modulus with FastMod
9aac9f90d5e56752cc6cbfac48063ad29a01143c replace modulus with FastMod (Martin Ankerl)
Pull request description:
Not sure if this is optimization is necessary, but anyway I have some spare time so here it is. This replaces the slow modulo operation with a much faster 64bit multiplication & shift. This works when the hash is uniformly distributed between 0 and 2^32-1. This speeds up the benchmark by a factor of about 1.3:
```
RollingBloom, 5, 1500000, 3.73733, 4.97569e-07, 4.99002e-07, 4.98372e-07 # before
RollingBloom, 5, 1500000, 2.86842, 3.81630e-07, 3.83730e-07, 3.82473e-07 # FastMod
```
Be aware that this changes the internal data of the filter, so this should probably
not be used for CBloomFilter because of interoperability problems.
Tree-SHA512: 04104f3fb09f56c9d14458a6aad919aeb0a5af944e8ee6a31f00e93c753e22004648c1cd65bf36752b6addec528d19fb665c27b955ce1666a85a928e17afa47a
* Use unordered_map in CSporkManager
In one of my profiling sessions with many InstantSend transactions
happening, calls into CSporkManager added up to about 1% of total CPU time.
This is easily avoidable by using unordered maps.
* Use std::unordered_map instead of std::map in limitedmap
* Use unordered_set for CNode::setAskFor
* Add serialization support for unordered maps and sets
* Use unordered_map for mapArgs and mapMultiArgs
* Let limitedmap prune in batches and use unordered_multimap
Due to the batched pruning, there is no need to maintain an ordered map
of values anymore. Only when nPruneAfterSize, there is a need to create
a temporary ordered vector of values to figure out what can be removed.
* Instead of using a multimap for mapAskFor, use a vector which we sort on demand
CNode::AskFor will now push entries into an initially unordered vector
instead of an ordered multimap. Only when we later want to use vecAskFor in
SendMessages, we sort the vector.
The vector will actually be mostly sorted in most cases as insertion order
usually mimics the desired ordering. Only the last few entries might need
some shuffling around. Doing the sort on-demand should be less wasteful
then trying to maintain correct order all the time.
* Fix compilation of tests
* Fix limitedmap tests
* Rename limitedmap to unordered_limitedmap to ensure backports conflict
This ensures that future backports that depends on limitedmap's ordering
conflict so that we are made aware of needed action.
* Fix compilation error on Travis
2019-04-11 14:42:14 +02:00
|
|
|
//BOOST_CHECK(it->first == i);
|
|
|
|
//BOOST_CHECK(it->second == i + 1);
|
2020-07-29 03:23:12 +02:00
|
|
|
|
2015-08-17 18:07:47 +02:00
|
|
|
// use find to check for the value
|
|
|
|
BOOST_CHECK(map.find(i)->second == i + 1);
|
2020-07-29 03:23:12 +02:00
|
|
|
|
2015-08-17 18:07:47 +02:00
|
|
|
// update and recheck
|
Collection of minor performance optimizations (#2855)
* Merge #13176: Improve CRollingBloomFilter performance: replace modulus with FastMod
9aac9f90d5e56752cc6cbfac48063ad29a01143c replace modulus with FastMod (Martin Ankerl)
Pull request description:
Not sure if this is optimization is necessary, but anyway I have some spare time so here it is. This replaces the slow modulo operation with a much faster 64bit multiplication & shift. This works when the hash is uniformly distributed between 0 and 2^32-1. This speeds up the benchmark by a factor of about 1.3:
```
RollingBloom, 5, 1500000, 3.73733, 4.97569e-07, 4.99002e-07, 4.98372e-07 # before
RollingBloom, 5, 1500000, 2.86842, 3.81630e-07, 3.83730e-07, 3.82473e-07 # FastMod
```
Be aware that this changes the internal data of the filter, so this should probably
not be used for CBloomFilter because of interoperability problems.
Tree-SHA512: 04104f3fb09f56c9d14458a6aad919aeb0a5af944e8ee6a31f00e93c753e22004648c1cd65bf36752b6addec528d19fb665c27b955ce1666a85a928e17afa47a
* Use unordered_map in CSporkManager
In one of my profiling sessions with many InstantSend transactions
happening, calls into CSporkManager added up to about 1% of total CPU time.
This is easily avoidable by using unordered maps.
* Use std::unordered_map instead of std::map in limitedmap
* Use unordered_set for CNode::setAskFor
* Add serialization support for unordered maps and sets
* Use unordered_map for mapArgs and mapMultiArgs
* Let limitedmap prune in batches and use unordered_multimap
Due to the batched pruning, there is no need to maintain an ordered map
of values anymore. Only when nPruneAfterSize, there is a need to create
a temporary ordered vector of values to figure out what can be removed.
* Instead of using a multimap for mapAskFor, use a vector which we sort on demand
CNode::AskFor will now push entries into an initially unordered vector
instead of an ordered multimap. Only when we later want to use vecAskFor in
SendMessages, we sort the vector.
The vector will actually be mostly sorted in most cases as insertion order
usually mimics the desired ordering. Only the last few entries might need
some shuffling around. Doing the sort on-demand should be less wasteful
then trying to maintain correct order all the time.
* Fix compilation of tests
* Fix limitedmap tests
* Rename limitedmap to unordered_limitedmap to ensure backports conflict
This ensures that future backports that depends on limitedmap's ordering
conflict so that we are made aware of needed action.
* Fix compilation error on Travis
2019-04-11 14:42:14 +02:00
|
|
|
auto jt = map.find(i);
|
|
|
|
map.update(jt, i + 2);
|
2015-08-17 18:07:47 +02:00
|
|
|
BOOST_CHECK(map.find(i)->second == i + 2);
|
|
|
|
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that we've exhausted the iterator
|
|
|
|
BOOST_CHECK(it == map.end());
|
|
|
|
|
|
|
|
// resize the map to 5 items
|
|
|
|
map.max_size(5);
|
|
|
|
|
|
|
|
// check that the max size and size are now 5
|
|
|
|
BOOST_CHECK(map.max_size() == 5);
|
|
|
|
BOOST_CHECK(map.size() == 5);
|
|
|
|
|
|
|
|
// check that items less than 5 have been discarded
|
|
|
|
// and items greater than 5 are retained
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
if (i < 5) {
|
|
|
|
BOOST_CHECK(map.count(i) == 0);
|
|
|
|
} else {
|
|
|
|
BOOST_CHECK(map.count(i) == 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// erase some items not in the map
|
|
|
|
for (int i = 100; i < 1000; i += 100) {
|
|
|
|
map.erase(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that the size is unaffected
|
|
|
|
BOOST_CHECK(map.size() == 5);
|
|
|
|
|
|
|
|
// erase the remaining elements
|
|
|
|
for (int i = 5; i < 10; i++) {
|
|
|
|
map.erase(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that the map is now empty
|
|
|
|
BOOST_CHECK(map.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|