Boost Flat Map

boost::container::flat_map is an alternative to std::map that is optimized for cache efficiency and fast lookups. Unlike std::map, which is implemented as a self-balancing binary search tree (RB-tree), flat_map is implemented as a sorted vector.

Key Differences:

Featureboost::container::flat_mapstd::map
Data StructureSorted vectorRed-Black Tree (BST)
Cache Efficiency✅ High (better CPU cache locality)❌ Low (pointers jump in memory)
Lookup Complexity🟢 O(log N) (binary search)🟢 O(log N) (tree search)
Insertion Complexity🔴 O(N) (due to shifting elements)🟢 O(log N)
Iteration SpeedFast (sequential memory access)Slow (pointer traversal)
Best ForSmall datasets, frequent lookupsLarge datasets, frequent insertions/deletions

🔹 Why Use boost::flat_map?

Better CPU Cache Locality:

  • Stores data in a contiguous memory block (unlike std::map‘s tree-based structure).
  • Faster lookups because of fewer cache misses.
  • More efficient for small to medium-sized datasets (e.g., less than 100,000 elements).

Fast Iteration:

  • flat_map is stored sequentially in memory, making iteration faster than std::map.
  • Ideal for cases where you need to iterate over sorted data.

Better Performance for Small Datasets:

  • If you have less than 10,000 elements, flat_map outperforms std::map in many cases.
  • Commonly used in HFT (High-Frequency Trading), game engines, and embedded systems.

Not good for frequent insertions/deletions:

  • Since flat_map is a sorted vector, inserting/deleting elements requires shifting other elements.
  • If you modify the map frequently, std::map is better because of its O(log N) insert/delete operations.

🔹 Example: Basic Usage of boost::flat_map

#include <boost/container/flat_map.hpp>
#include <iostream>

int main() {
    boost::container::flat_map<int, std::string> myMap;

    myMap[3] = "Three";
    myMap[1] = "One";
    myMap[2] = "Two";

    // Iterating over elements (always sorted)
    for (const auto& pair : myMap)
        std::cout << pair.first << ": " << pair.second << std::endl;

    return 0;
}

Output (Always Sorted)

1: One
2: Two
3: Three

📌 Notice: Unlike std::unordered_map, boost::flat_map maintains order!


🔹 Performance Comparison: boost::flat_map vs. std::map

Let’s compare the lookup and insertion times for both:

🔹 Lookup Performance (find() operation)

Dataset Sizeboost::flat_map (Binary Search)std::map (Tree Search)
1,000 elements🟢 Faster🔴 Slower
10,000 elements🟢 Faster🟡 Similar
1,000,000 elements🔴 Slower🟢 Faster

🔹 boost::flat_map is faster for small datasets but gets slower for very large datasets.


🔹 Insertion Performance (insert() operation)

Dataset Sizeboost::flat_map (O(N))std::map (O(log N))
1,000 elements🔴 Slower (shifting needed)🟢 Faster
10,000 elements🔴 Much slower🟢 Faster
1,000,000 elements🔴 Very slow🟢 Much faster

🔹 If you insert/delete elements frequently, std::map is better.


🔹 Advanced Features of boost::flat_map

1️⃣ Bulk Insertions (reserve() optimization)

To avoid costly reallocation during insertions, preallocate memory using reserve():

#include <boost/container/flat_map.hpp>
#include <iostream>

int main() {
    boost::container::flat_map<int, std::string> myMap;
    
    myMap.reserve(100);  // Preallocate space for 100 elements (improves performance)

    for (int i = 0; i < 100; ++i) {
        myMap[i] = "Value " + std::to_string(i);
    }

    return 0;
}

📌 Using reserve() can significantly reduce memory reallocation overhead.


2️⃣ Range Insertions (insert() with multiple elements)

flat_map supports bulk insertions from iterators:

#include <boost/container/flat_map.hpp>
#include <vector>
#include <iostream>

int main() {
    boost::container::flat_map<int, std::string> myMap;
    
    std::vector<std::pair<int, std::string>> data = {
        {4, "Four"}, {2, "Two"}, {3, "Three"}, {1, "One"}
    };

    // Bulk insert (data must be sorted)
    myMap.insert(data.begin(), data.end());

    for (const auto& pair : myMap)
        std::cout << pair.first << ": " << pair.second << std::endl;

    return 0;
}

📌 Bulk insertions are faster than inserting elements one-by-one!


🔹 When Should You Use boost::flat_map?

Use boost::flat_map if:

  • You have small to medium-sized datasets (< 100,000 elements).
  • You prioritize fast lookups over fast insertions.
  • You need better cache locality and fast iteration.
  • Your data is mostly read-heavy, not modified often.

Avoid boost::flat_map if:

  • You frequently insert or delete elements.
  • You work with large datasets (> 1,000,000 elements).
  • You require frequent random access insertions (prefer std::map).

🔹 Summary Table: boost::flat_map vs std::map

Featureboost::flat_mapstd::map
Data StructureSorted VectorRed-Black Tree
Lookup (find())🟢 Faster (binary search, O(log N))🟢 O(log N)
Insertion (insert())🔴 Slower (O(N), shifting needed)🟢 O(log N)
Iteration🟢 Faster (cache-friendly)🔴 Slower (pointers)
Best Use CaseSmall datasets, frequent lookupsLarge datasets, frequent inserts/deletes

🔹 Final Thoughts

  • boost::flat_map is best for performance-critical applications where lookup speed matters more than insertion speed.
  • Used in finance, HFT, game engines, AI, and embedded systems.
  • Not a replacement for std::map, but a great alternative for specific use cases.