当前位置: 首页 > news >正文

C++ 高性能容器:ankerl::unordered_dense::map

介绍

ankerl::unordered_dense::map 是一个 高性能哈希表容器,来自开源库 unordered_dense,由 Martin Ankerl 开发。
它的作用和标准库中的 std::unordered_map 类似,用于存储键值对,但有以下优点:

特性说明
🚀 更快性能通常比 std::unordered_map 更好,特别是在查找、插入、大量数据时
📦 内存紧凑内存布局更紧凑,缓存友好,避免了节点式内存开销
🔁 开放寻址 (Open Addressing)使用了 Robin Hood Hashing,避免链表结构,提升性能一致性
🧠 数据局部性更好有利于 CPU 缓存利用,提升实际运行速度
🛠️ 无依赖是一个头文件库,直接包含即可使用,不需要链接其他库

和std::unordered_map的区别

项目std::unordered_mapankerl::unordered_dense::map
结构链表式哈希桶扁平数组 + Robin Hood
查找性能中等,可能退化极快且稳定
内存使用较高(每个节点有额外指针)更低
迭代顺序不确定稳定迭代(插入顺序)
线程安全
C++标准C++11 以上C++17 以上(推荐)

测试目标

  • 插入 N 个随机整数作为键,值为序号
  • 随机查找 N 次,记录时间消耗
  • 对比两个容器的性能差异
#include <iostream>
#include <unordered_map>
#include <ankerl/unordered_dense.h>
#include <chrono>
#include <vector>
#include <random>constexpr size_t N = 1'000'000;std::vector<int> generate_random_keys(size_t n) {std::vector<int> keys(n);std::mt19937 rng(12345);std::uniform_int_distribution<int> dist(1, n * 10);for (size_t i = 0; i < n; ++i) {keys[i] = dist(rng);}return keys;
}template<typename Map>
void benchmark(const std::string& name, const std::vector<int>& keys) {Map map;auto t1 = std::chrono::high_resolution_clock::now();for (size_t i = 0; i < keys.size(); ++i) {map[keys[i]] = static_cast<int>(i);}auto t2 = std::chrono::high_resolution_clock::now();std::cout << name << " insert time: "<< std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()<< " ms\n";size_t found = 0;auto t3 = std::chrono::high_resolution_clock::now();for (size_t i = 0; i < keys.size(); ++i) {if (map.find(keys[i]) != map.end()) {++found;}}auto t4 = std::chrono::high_resolution_clock::now();std::cout << name << " lookup time: "<< std::chrono::duration_cast<std::chrono::milliseconds>(t4 - t3).count()<< " ms (found: " << found << ")\n\n";
}int main() {auto keys = generate_random_keys(N);benchmark<std::unordered_map<int, int>>("std::unordered_map", keys);benchmark<ankerl::unordered_dense::map<int, int>>("ankerl::unordered_dense::map", keys);return 0;
}

在这里插入图片描述

总结

操作std::unordered_mapankerl::unordered_dense::map差距
插入 100 万个键
查找 100 万个键
内存占用
代码兼容性标准非标准⚠️

为什么两者会有这样的差距

1、底层实现结构不同
特性std::unordered_mapankerl::unordered_dense::map
哈希碰撞处理分离链接(chaining)
每个桶是链表或红黑树
开放寻址(open addressing)
Robin Hood Hashing
存储结构哈希桶数组 + 动态链表节点扁平数组,紧凑布局
内存分布离散(每个节点分配在堆上)连续(所有元素集中在数组中)
2、CPU 缓存友好性

现代 CPU 在访问内存时,最重要的就是 cache locality(缓存局部性)。

  • std::unordered_map 节点式结构,数据跳跃,cache miss 多。
  • ankerl::unordered_dense::map 紧凑数组结构,cache hit 高,速度自然快。
3、内存分配频率
  • std::unordered_map 插入每个元素时都需要 独立分配节点内存,开销大。
  • ankerl::unordered_dense::map 一次性分配数组空间,插入快得多。
4、哈希冲突处理方式不同
  • std::unordered_map 用链表或红黑树存储冲突项 → 查找时间不稳定(最差的情况是退化成单链表)

  • ankerl::unordered_dense::map 用 Robin Hood Hashing:

    • 冲突时较老元素会被“抢占”回前面

    • 查找路径更平均 → 查找速度更稳定

5、内存占用对比
  • std::unordered_map 每个节点有额外结构:指针、allocator header 等

  • ankerl::unordered_dense::map 只需两个数组(key-value + metadata)

参考链接

https://zhuanlan.zhihu.com/p/1891902733864375991

http://www.lryc.cn/news/604358.html

相关文章:

  • 元码智能“大眼睛”机器人首发,智启生活新纪元!
  • RabbitMQ 发送方确认的两大工具 (With Spring Boot)
  • Metering Solution for Solar + Storage光伏+储能计量解决方案 UL 2735 Certification功率表能源监测电表
  • 第2章 cmd命令基础:常用基础命令(2)
  • c++之基础B之sort排序(第三个参数没有)(第二课)
  • 在macOS上使用VS Code和Clang配置C++开发环境
  • 湖北大学暑期实训优秀作品:面向美丽中国的数据化可视平台
  • 涉及实验(随机分组)的一些概念
  • 【swoole Windows 开发(swoole-cli 开发 hyperf)】
  • 时间序列预测的自回归方法
  • Product Hunt 每日热榜 | 2025-07-30
  • tplink er2260t配置带vlan的pppoe拨号
  • Java学习第八十九部分——“层”(续)
  • 学会使用golang zap日志库
  • 【动态规划算法】斐波那契数列模型
  • 嵌入式开发学习———Linux环境下数据结构学习(五)
  • 服务器与电脑主机的区别,普通电脑可以当作服务器用吗?
  • 从结构到交互:HTML5进阶开发全解析——语义化标签、Canvas绘图与表单设计实战
  • MCP提示词工程:上下文注入的艺术与科学
  • 【机器学习11】“分类算法“评估矩阵:从对数损失、AUC和ROC、混淆矩阵与分类报告等角度来评估算法
  • 小架构step系列30:多个校验注解
  • Mysql事务基础
  • LeetCode Hot 100:15. 三数之和
  • 大模型赋能:台风“竹节草”精细化路径预测实践
  • 硬件电路设计(基本元器件)
  • 深入理解C++编译器优化:从O0到O3及构建模式详解
  • 【从零实践Onvif】01、Onvif详细介绍(从Onvif客户端开发的角度认识Onvif、Web Servies、WSDL、SOAP)
  • 压测合格标准
  • 智能体产品化的关键突破:企业智能化转型的“最后一公里”如何迈过?
  • 【刷题】东方博宜oj 1307 - 数的计数