From 95d9bb50ca6834fe65013bed0e04e6df94bedd27 Mon Sep 17 00:00:00 2001 From: Jidong Xiao Date: Tue, 11 Mar 2025 00:56:33 -0400 Subject: [PATCH] adding benchmarks and readme --- .../optimization/erase/map_erase_fast.cpp | 20 ++++++ .../optimization/erase/map_erase_slow.cpp | 20 ++++++ lectures/optimization/map_erase/README.md | 69 +++++++++++++++++++ .../optimization/map_erase/map_erase_fast.cpp | 20 ++++++ .../optimization/map_erase/map_erase_slow.cpp | 20 ++++++ 5 files changed, 149 insertions(+) create mode 100644 lectures/optimization/erase/map_erase_fast.cpp create mode 100644 lectures/optimization/erase/map_erase_slow.cpp create mode 100644 lectures/optimization/map_erase/README.md create mode 100644 lectures/optimization/map_erase/map_erase_fast.cpp create mode 100644 lectures/optimization/map_erase/map_erase_slow.cpp diff --git a/lectures/optimization/erase/map_erase_fast.cpp b/lectures/optimization/erase/map_erase_fast.cpp new file mode 100644 index 0000000..ccbd380 --- /dev/null +++ b/lectures/optimization/erase/map_erase_fast.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() { + const int N = 1000000; + std::map m; + + // fill the map with some values + for (int i = 0; i < N; ++i) { + m[i] = i; + } + + // erase all elements using iterators + for (std::map::iterator itr = m.begin(); itr != m.end(); ) { + itr = m.erase(itr); // erase using iterator and move to the next element + } + + return 0; +} + diff --git a/lectures/optimization/erase/map_erase_slow.cpp b/lectures/optimization/erase/map_erase_slow.cpp new file mode 100644 index 0000000..5b46dd2 --- /dev/null +++ b/lectures/optimization/erase/map_erase_slow.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() { + const int N = 1000000; + std::map m; + + // fill the map with some values + for (int i = 0; i < N; ++i) { + m[i] = i; + } + + // erase by key + for (int i = 0; i < N; ++i) { + m.erase(i); + } + + return 0; +} + diff --git a/lectures/optimization/map_erase/README.md b/lectures/optimization/map_erase/README.md new file mode 100644 index 0000000..0f78388 --- /dev/null +++ b/lectures/optimization/map_erase/README.md @@ -0,0 +1,69 @@ +# `erase by iterator` vs. `erase by key` in C++ + +## Overview + +erasing by iterator in std::maps is typically faster than erasing by key. + +## Erasing by Iterator: + +- When you erase an element using an iterator, the map already has a direct reference to the node that contains the element to be erased. + +- The iterator is a pointer to the element (node) in the underlying tree structure (which is usually a red-black tree for std::map). + +## Erasing by Key: + +- When you erase an element by key, std::map first has to search for the key. + +- It does this by traversing the red-black tree to find the node that matches the key. + +- After finding the node, it performs the same operation as erase(iterator), but since it had to perform a search to locate the key, this is slower than directly accessing the iterator. + +## Benchmarks + +Compile and run these 2 programs to see the performance difference. + +[map_erase_slow.cpp](map_erase_slow.cpp) [map_erase_fast.cpp](map_erase_fast.cpp) + +Both programs just creates a map containing 1 millions integers, and then erase these 1 millions integers. As can be seen from the following results, erasing by iterators is much faster than erasing by key. + +```console +$g++ map_erase_slow.cpp -o map_erase_slow +$g++ map_erase_fast.cpp -o map_erase_fast + +$time ./map_erase_slow + +real 0m0.640s +user 0m0.624s +sys 0m0.016s + +$time ./map_erase_fast + +real 0m0.406s +user 0m0.386s +sys 0m0.020s + +$time ./map_erase_fast + +real 0m0.382s +user 0m0.374s +sys 0m0.008s + +$time ./map_erase_slow + +real 0m0.629s +user 0m0.617s +sys 0m0.012s + +$time ./map_erase_slow + +real 0m0.632s +user 0m0.623s +sys 0m0.009s + +$time ./map_erase_fast + +real 0m0.383s +user 0m0.366s +sys 0m0.017s + +``` diff --git a/lectures/optimization/map_erase/map_erase_fast.cpp b/lectures/optimization/map_erase/map_erase_fast.cpp new file mode 100644 index 0000000..ccbd380 --- /dev/null +++ b/lectures/optimization/map_erase/map_erase_fast.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() { + const int N = 1000000; + std::map m; + + // fill the map with some values + for (int i = 0; i < N; ++i) { + m[i] = i; + } + + // erase all elements using iterators + for (std::map::iterator itr = m.begin(); itr != m.end(); ) { + itr = m.erase(itr); // erase using iterator and move to the next element + } + + return 0; +} + diff --git a/lectures/optimization/map_erase/map_erase_slow.cpp b/lectures/optimization/map_erase/map_erase_slow.cpp new file mode 100644 index 0000000..5b46dd2 --- /dev/null +++ b/lectures/optimization/map_erase/map_erase_slow.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() { + const int N = 1000000; + std::map m; + + // fill the map with some values + for (int i = 0; i < N; ++i) { + m[i] = i; + } + + // erase by key + for (int i = 0; i < N; ++i) { + m.erase(i); + } + + return 0; +} +