folly/AtomicHashmap.h

folly/AtomicHashmap.h introduces a synchronized UnorderedAssociativeContainer implementation designed for extreme performance in heavily multithreaded environments (about 2-5x faster than tbb::concurrent_hash_map) and good memory usage properties. Find and iteration are wait-free, insert has key-level lock granularity, there is minimal memory overhead, and permanent 32-bit ids can be used to reference each element.

Limitations


Although it can provide extreme performance, AtomicHashmap has some unique limitations as well.

  • The space for erased elements cannot be reclaimed (they are tombstoned forever) so it's generally not a good idea to use this if you're erasing things a lot.

  • Only supports 32 or 64 bit keys - this is because they must be atomically compare-and-swap'ed.

  • Growth beyond initialization reduces performance - if you don't know the approximate number of elements you'll be inserting into the map, you probably shouldn't use this class.

  • Must manage synchronization externally in order to modify values in the map after insertion. Lock pools are a common way to do this, or you may consider using folly::PackedSyncPtr<T> as your ValueT.

  • Must define special reserved key values for empty, erased, and locked elements.

For a complete list of limitations and departures from the UnorderedAssociativeContainer concept, see folly/AtomicHashMap.h

Unique Features


  • value_type references remain valid as long as the map itself. Note this is not true for most other probing hash maps which will move elements when rehashing, which is necessary for them to grow. AtomicHashMap grows by chaining additional slabs, so elements never need to be moved.

  • Unique 32-bit ids can be used to reference elements in the map via iterator::getIndex(). This can be helpful to save memory in the rest of the application by replacing 64-bit pointers or keys.

  • Iterators are never invalidated. This means you can iterate through the map while simultaneously inserting and erasing. This is particularly useful for non-blocking map serialization.

Usage


Usage is similar to most maps, although note the conspicuous lack of operator[] which encourages non thread-safe access patterns.

Below is a synchronized key counter implementation that allows the counter values to be incremented in parallel with serializing all the values to a string.

   class Counters {
private:
AtomicHashMap<int64_t,int64_t> ahm; public:
explicit Counters(size_t numCounters) : ahm(numCounters) {} void increment(int64_t obj_id) {
auto ret = ahm.insert(make_pair(obj_id, ));
if (!ret.second) {
// obj_id already exists, increment
NoBarrier_AtomicIncrement(&ret.first->second, );
}
} int64_t getValue(int64_t obj_id) {
auto ret = ahm.find(obj_id);
return ret != ahm.end() ? ret->second : ;
} // Serialize the counters without blocking increments
string toString() {
string ret = "{\n";
ret.reserve(ahm.size() * );
for (const auto& e : ahm) {
ret += folly::to<string>(
" [", e.first, ":", NoBarrier_Load(&e.second), "]\n");
}
ret += "}\n";
return ret;
}
};

Implementation


AtomicHashMap is a composition of AtomicHashArray submaps, which implement the meat of the functionality. Only one AHA is created on initialization, and additional submaps are appended if the first one gets full. If the AHM grows, there will be multiple submaps that must be probed in series to find a given key. The more growth, the more submaps will be chained, and the slower it will get. If the initial size estimate is good, only one submap will ever be created and performance will be optimal.

AtomicHashArray is a fixed-size probing hash map (also referred to as an open addressed hash map) where hash collisions are resolved by checking subsequent elements. This means that they can be allocated in slabs as arrays of value_type elements, have excellent cache performance, and have no memory overhead from storing pointers.

The algorithm is simple - when inserting, the key is hash-mod'ed to an offset, and that element-key is atomically compare-and-swap'ed with the locked key value. If successful, the value is written and the element-key is unlocked by setting it to the input key value. If the compare fails, the next element is tried until success or the map is full.

Finds are even simpler. The key is hash-mod'ed to an offset, and the element-key is examined. If it is the same as the input key, the reference is returned, if it's the empty key, failure is returned, otherwise the next key is tried. This can be done wait-free without any atomic instructions because the elements are always in a valid state.

Erase is done by finding the key, then compare-and-swap'ing the element-key with the reserved erased key value. If the swap succeeds, return success, otherwise return failure (the element was erased by a competing thread). If the key does not exist, return failure.

AtomicHashMap的更多相关文章

  1. folly::AtomicHashmap源码分析(二)

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ 背景 上一篇只是细致的把源码分析了一遍,而源码背后的设计思想并没有写,设计思想往往是最重要的,没有它,基本无法做整 ...

  2. folly::AtomicHashmap源码分析(一)

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ Atomic的两点背景 看下这个场景,老张去厕所,发现门是锁着的,他就在门口等着里边人出来,此时小王也来了,他想了 ...

  3. folly学习心得(转)

    原文地址:  https://www.cnblogs.com/Leo_wl/archive/2012/06/27/2566346.html   阅读目录 学习代码库的一般步骤 folly库的学习心得 ...

  4. Folly: Facebook Open-source Library Readme.md 和 Overview.md(感觉包含的东西并不多,还是Boost更有用)

    folly/ For a high level overview see the README Components Below is a list of (some) Folly component ...

  5. 《HelloGitHub》第 75 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

随机推荐

  1. c# IE 清除缓存

    Response.Buffer = true; Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-); Response.Expir ...

  2. 【PL/SQL编程】变量和常量

    1. 变量格式 <变量名><数据类型>[(长度):=<初始值>]; v_countryname varchar2(50):='中国'; 2. 常量格式 <常量 ...

  3. javaScript高程笔记--最佳实践

    1.可维护性 <1>什么是可维护的代码 (1)可理解性 (2)直观性 (3)可适应性 (4)可扩展性 (5)可调试性 <2>代码约定 (1)可读性---适当的进行注释[函数和方 ...

  4. [置顶] 滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理

    上周末,滴滴与360都开源了各自的插件化框架,VirtualAPK与RePlugin,作为一个插件化方面的狂热研究者,在周末就迫不及待的下载了Virtualapk框架来进行研究,本篇博客带来的是Vir ...

  5. 在Fragment中加一个嵌套了ListView的ScrollView(一)

    首先介绍一下这个程序的功能: 1.顶部有两个可以切换Fragment的Button 2.在其中一个Fragment中里有个ScrollView,ScrollView中有ViewFlipper,List ...

  6. iOS-----AVFoundation框架的功能详解

    使用AVFoundation拍照和录制视频 需要开发自定义的拍照和录制视频功能,可借助于AVFoundation框架来实现,该框架提供了大量的类来完成拍照和录制视频.主要使用如下类: AVCaptur ...

  7. python3 使用matplotlib画图问题

    保存图片的问题 在画子图并保存图片的时候,用如下代码保存的图片总是不能显示,但是在运行的过程中能够正常显示图片. # coding:utf-8 from pylab import * # 创建子图 f ...

  8. ubuntu 添加应用到Dash启动器

    打开终端输入 $sudo vim /usr/share/applications/name.desktop name是你的程序标识名称 在打开的编辑器中添加以下内容,这里以配置NetBeans为例: ...

  9. hadoop常见错误总结三

    问题导读:1.... could only be replicated to 0 nodes, instead of 1 ...可能的原因是什么?2.Error: java.lang.NullPoin ...

  10. L2-017. 人以群分

    社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的).要求两类人群的规模尽可能接近 ...