Last active
March 2, 2020 20:46
-
-
Save ikt32/02dc6f850eab905d7a8a5e41ef0b2246 to your computer and use it in GitHub Desktop.
Compare stl::find_if vs simple search
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include <tuple> | |
#include <vector> | |
#include <algorithm> | |
#include <string> | |
#include <random> | |
#include <chrono> | |
#include <iostream> | |
typedef uint32_t Hash; | |
std::vector<std::tuple<Hash, int, int, int>> addonImages; | |
bool isPresentinAddonImages_STL(Hash hash) { | |
return addonImages.end() != std::find_if(addonImages.begin(), addonImages.end(), [&hash](const std::tuple<Hash, int, int, int>& element) { | |
return std::get<0>(element) == hash; | |
}); | |
} | |
bool isPresentinAddonImages_loop(Hash hash) { | |
for (const auto& addonImage : addonImages) { | |
if (std::get<0>(addonImage) == hash) | |
return true; | |
} | |
return false; | |
} | |
Hash joaat(std::string s) { | |
std::transform(s.begin(), s.end(), s.begin(), ::tolower); | |
Hash hash = 0; | |
for (int i = 0; i < s.size(); i++) { | |
hash += s[i]; | |
hash += (hash << 10); | |
hash ^= (hash >> 6); | |
} | |
hash += (hash << 3); | |
hash ^= (hash >> 11); | |
hash += (hash << 15); | |
return hash; | |
} | |
int main() { | |
Hash needle = joaat("needle"); | |
std::mt19937 rng; | |
rng.seed(std::random_device()()); | |
std::uniform_int_distribution<std::mt19937::result_type> dist(1, 9999); // distribution in range [1, 6] | |
for (int i = 0; i < 1000; i++) { | |
Hash hash = joaat("notneedle" + std::to_string(dist(rng))); | |
addonImages.push_back(std::make_tuple(hash, 1, 480, 270)); | |
} | |
addonImages.push_back(std::make_tuple(needle, 1, 480, 270)); | |
for (int i = 0; i < 1000; i++) { | |
Hash hash = joaat("notneedle" + std::to_string(dist(rng))); | |
addonImages.push_back(std::make_tuple(hash, 1, 480, 270)); | |
} | |
std::cout << "Elements: " << addonImages.size() << "\n"; | |
auto t1 = std::chrono::high_resolution_clock::now(); | |
bool res = isPresentinAddonImages_STL(needle); | |
auto t2 = std::chrono::high_resolution_clock::now(); | |
std::cout << "STL:\nDid "; | |
if (!res) { | |
std::cout << "not "; | |
} | |
std::cout << "find the needle in " | |
<< std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() | |
<< " ns!\n"; | |
t1 = std::chrono::high_resolution_clock::now(); | |
res = isPresentinAddonImages_loop(needle); | |
t2 = std::chrono::high_resolution_clock::now(); | |
std::cout << "loop:\nDid"; | |
if (!res) { | |
std::cout << "not "; | |
} | |
std::cout << "find the needle in " | |
<< std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() | |
<< " ns!\n"; | |
return 0; | |
} | |
Thanks for the suggestion. Wew, this was 3 years ago, I don't even remember what I ended up doing. Running the "benchmark" now the difference is minimal anyway, with no clear winner with either a reference or by value. Plus, the collection size usually is less than 1000 anyway, or other issues might occur ;)
On my machine, under MSVC x64 Release build, passing by value is 3 times slower than passing by reference on average.
After the fix, no significant difference anymore.
I'm just curious about the performence of find_if, and searching on Google brings me here.
Ah yeah, under debug mode the difference is significant, I forgot to mention I tested with a release type build this time.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
for (auto addonImage : addonImages)
should be:
for (const auto& addonImage : addonImages)
this makes the most difference.