I was accidentally surprised to found that inserting sorted keys into std::set is much much faster than inserting shuffled keys. This is somewhat counterintuitive since a red-black tree (I verified that std::set is implemented as a red-black tree on my system) as a self-balanced binary search tree, would need to do a lot of rebalancing opeartions to insert a sequence of sorted keys, thus inserting sorted keys should take more time than inserting shuffled keys.
But the fact is, inserting sorted keys can be up to 15 times faster than inserting shuffled keys! Here is my testing code and some results:
#include <algorithm> #include <chrono> #include <iostream> #include <random> #include <set> #include <vector> using namespace std; int64_t insertion_time(const vector<int> &keys) { auto start = chrono::system_clock::now(); set<int>(keys.begin(), keys.end()); auto stop = chrono::system_clock::now(); auto elapsed = chrono::duration_cast<chrono::milliseconds>(stop - start); return elapsed.count(); } int main() { size_t test_size; cout << "test size: "; cin >> test_size; vector<int> keys(test_size); for (int i = 0; i < test_size; ++i) { keys[i] = i; } // whether shuffled case or sorted case took first was irrelevant and results were similar auto rng = std::default_random_engine {}; shuffle(keys.begin(), keys.end(), rng); cout << "shuffled: " << insertion_time(keys) << endl; sort(keys.begin(), keys.end()); cout << "sorted: " << insertion_time(keys) << endl; return 0; } // i7 8700, 32 GB RAM, WIN10 2004, g++ -O3 main.cpp // An interesting observation is that the difference becomes larger as test_size being larger. // Similar results showed up for my handwritten red-black tree and other // machines( or other compilers, operating systems etc) C:\Users\Leon\Desktop\testSetInsertion>a test size: 1000000 shuffled: 585 sorted: 96 C:\Users\Leon\Desktop\testSetInsertion>a test size: 3000000 shuffled: 2480 sorted: 296 C:\Users\Leon\Desktop\testSetInsertion>a test size: 5000000 shuffled: 4805 sorted: 484 C:\Users\Leon\Desktop\testSetInsertion>a test size: 10000000 shuffled: 11537 sorted: 977 C:\Users\Leon\Desktop\testSetInsertion>a test size: 30000000 shuffled: 46239 sorted: 3076 Anyone explains this please? I guess that this has something to do with cache locality since when inserting sorted keys, rebalancing typically involves those nodes that were most recently inserted. But above is just my guess and I know very little about cache locality.