I did some profiling and got the following results (MSVS 2008, /O2, release build, launching .exe separately).
EDIT - Now I realize I actually f*cked up my first test, because I didn't split the building and searching test. Though it didn't change the "winners", I made some new tests. So, here are the results when we split them.
First, if there are almost no bad search requests (4 million good search attempts).
[ RUN ] Containers.DictionaryPrepare
[ OK ] Containers.DictionaryPrepare (234 ms)
[ RUN ] Containers.VectorPrepare
[ OK ] Containers.VectorPrepare (704 ms)
[ RUN ] Containers.SetPrepare
[ OK ] Containers.SetPrepare (593 ms)
[ RUN ] Containers.MultisetPrepare
[ OK ] Containers.MultisetPrepare (578 ms)
[ RUN ] Containers.UnorderedSetPrepare
[ OK ] Containers.UnorderedSetPrepare (266 ms)
[ RUN ] Containers.UnorderedMultisetPrepare
[ OK ] Containers.UnorderedMultisetPrepare (375 ms)
[ RUN ] Containers.VectorSearch
[ OK ] Containers.VectorSearch (4484 ms)
[ RUN ] Containers.SetSearch
[ OK ] Containers.SetSearch (5469 ms)
[ RUN ] Containers.MultisetSearch
[ OK ] Containers.MultisetSearch (5485 ms)
[ RUN ] Containers.UnorderedSet
[ OK ] Containers.UnorderedSet (1078 ms)
[ RUN ] Containers.UnorderedMultiset
[ OK ] Containers.UnorderedMultiset (1250 ms)
[----------] 11 tests from Containers (20516 ms total)
This profiling shows that you should use "normal" container variations instead of "multi", and you should choose the unordered_set
. It's great in building time and search operations time.
Here are the results for another case (guess, it's not about your app, but just for it to be), when the amount of bad searches equals the amount of good searches (and equals 2 million). The winner remains the same.
Also note, that for static dictionaries vector
performs better (though need more time for initialization), than set
, but well, it will suck if you have to add elements.
[ RUN ] Containers.DictionaryPrepare
[ OK ] Containers.DictionaryPrepare (235 ms)
[ RUN ] Containers.VectorPrepare
[ OK ] Containers.VectorPrepare (718 ms)
[ RUN ] Containers.SetPrepare
[ OK ] Containers.SetPrepare (578 ms)
[ RUN ] Containers.MultisetPrepare
[ OK ] Containers.MultisetPrepare (579 ms)
[ RUN ] Containers.UnorderedSetPrepare
[ OK ] Containers.UnorderedSetPrepare (265 ms)
[ RUN ] Containers.UnorderedMultisetPrepare
[ OK ] Containers.UnorderedMultisetPrepare (375 ms)
[ RUN ] Containers.VectorSearch
[ OK ] Containers.VectorSearch (3375 ms)
[ RUN ] Containers.SetSearch
[ OK ] Containers.SetSearch (3656 ms)
[ RUN ] Containers.MultisetSearch
[ OK ] Containers.MultisetSearch (3766 ms)
[ RUN ] Containers.UnorderedSet
[ OK ] Containers.UnorderedSet (875 ms)
[ RUN ] Containers.UnorderedMultiset
[ OK ] Containers.UnorderedMultiset (1016 ms)
[----------] 11 tests from Containers (15438 ms total)
Testing code:
TEST(Containers, DictionaryPrepare) {
EXPECT_FALSE(strings_initialized);
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
strings.push_back(generate_string());
}
}
TEST(Containers, VectorPrepare) {
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
vec.push_back(strings[i]);
}
sort(vec.begin(), vec.end());
}
TEST(Containers, SetPrepare) {
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
set.insert(strings[i]);
}
}
TEST(Containers, MultisetPrepare) {
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
multiset.insert(strings[i]);
}
}
TEST(Containers, UnorderedSetPrepare) {
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
uo_set.insert(strings[i]);
}
}
TEST(Containers, UnorderedMultisetPrepare) {
for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
uo_multiset.insert(strings[i]);
}
}
TEST(Containers, VectorSearch) {
for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
std::binary_search(vec.begin(), vec.end(), strings[rand() % TOTAL_ELEMENTS]);
}
for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
std::binary_search(vec.begin(), vec.end(), NONEXISTENT_ELEMENT);
}
}
TEST(Containers, SetSearch) {
for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
set.find(strings[rand() % TOTAL_ELEMENTS]);
}
for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
set.find(NONEXISTENT_ELEMENT);
}
}
TEST(Containers, MultisetSearch) {
for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
multiset.find(strings[rand() % TOTAL_ELEMENTS]);
}
for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
multiset.find(NONEXISTENT_ELEMENT);
}
}
TEST(Containers, UnorderedSet) {
for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
uo_set.find(strings[rand() % TOTAL_ELEMENTS]);
}
for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
uo_set.find(NONEXISTENT_ELEMENT);
}
}
TEST(Containers, UnorderedMultiset) {
for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
uo_multiset.find(strings[rand() % TOTAL_ELEMENTS]);
}
for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
uo_multiset.find(NONEXISTENT_ELEMENT);
}
}