gpt4 book ai didi

c++ - 在一个线程上删除具有数百万个字符串的大型 HashMap 会影响另一个线程的性能

转载 作者:行者123 更新时间:2023-12-01 12:41:10 28 4
gpt4 key购买 nike

所以我有这个 C++ 程序,它基本上解析巨大的数据集文件并将内容加载到内存中的 hashmap( 这部分在主线程中被限制 ,所以它永远不会占用大量时间)。完成后,我将指针翻转到新的内存位置,并对旧的内存位置调用 delete。除此之外,程序通过在内存映射(在主线程上)中查找内容来进行传入请求匹配。假设那些巨大的 map 被包裹在 Evaluator 中。类(class):

Evaluator* oldEvaluator = mEvaluator;
Evaluator* newEvaluator = parseDataSet();
mEvaluator = newEvaluator;
delete oldEvaluator;

//And then on request processing:
mEvaluator.lookup(request)

map 可以包含数百万个字符串对象,如 key .它们是常规字符串,可以是 ip、UserAgent 等请求属性,但每个字符串都是插入到 STL unordered_map 中的字符串对象。

数据集会定期更新,但大多数时候程序只是对内存中的数据集进行请求属性匹配,而且它很好、高效且没有错误,除非发生新数据集的大量消耗。使用这个大数据集的另一种方法是 使用流媒体 ,但这是一个相对长期的解决方案。

它曾经是一个使用事件驱动模型的单线程程序,但是每次放置一个完整的新集合并调用销毁时,删除整个事物花费的时间太长,从而阻塞了请求处理。

所以我把 将此类映射删除到单独的线程 .问题是现在删除和请求处理似乎同时发生,我可以看到请求处理线程非常明显,急剧放缓。

当然,主机上还有其他进程在运行,我确实希望这 2 个线程竞争 CPU 周期。但我没想到请求匹配线程会大幅放缓。平均而言,一个请求应该被处理 500us 级别,但是当删除线程正在运行时,它会慢到 5ms。有时 cpu 会中断匹配的线程(因为它花费的时间太长),它可能会持续 50 毫秒,或 120 毫秒等。在极端情况下,一个请求可能需要整个 1000 毫秒来处理,这大约是整个时间数据结构删除需要另一个线程。

了解这种减速的根本原因的最佳方法是什么? 是否更多是 CPU 或内存带宽瓶颈 ?我在想象,只要我把它放在一个单独的线程上,我就不会在意它有多慢,因为它毕竟必须一个一个地删除字符串对象,所以我没想到它会影响另一个线程......

编辑 :多亏了一些评论/答案似乎已经指出了几个可能的原因:
  • 内存碎片 .因为不常访问的字符串存储在更昂贵的内存位置(因此缓存未命中),或者因为它存储在具有许多指针的 unordered_map 中,或者因为系统在执行内存压缩的同时删除所有地方的孔?但是为什么这会影响另一个线程的缓慢?
  • 一条评论提到它是 由于线程安全锁定导致的堆争用 ?所以这个程序的整个堆都锁定了,因为一个线程正忙于删除阻止另一个线程访问堆内存的漏洞?为了澄清一下,该程序故意从不分配东西并同时释放其他东西,并且它只有 2 个线程,一个专用于删除。

  • 那我该怎么办呢?我试过 Jemalloc虽然不确定我是否完全正确地使用它 --- 似乎包括 -ljemalloc在链接器行中只是神奇地替换了 libc 的 malloc?我试过了,没有性能差异,但我可能用错了。我的程序没有做任何显式的 malloc,一切都是 new事先未知大小,并与指针和 STL 映射连接在一起。

    以及存储在 中的所有字符串 key 专门用于快速查找,因此它们不能存储在带有索引的 vector 中,即使这会产生连续的内存空间,定位它们也会很糟糕。所以,
  • 我如何才能确定上述 2 个内存问题是原因(任何工具/指标?)
  • 在不将消费模型更改为流媒体的情况下,我可以做些什么来修复它?假设根本原因是上述 2,似乎我应该做两件事之一/两件事:1)分配我所有的 STL 映射以及所有来自一个池的对象?我怎么做? 2) 减少堆争用(我不知道 Jemalloc 是否解决了我的情况)
  • 最佳答案

    只存储一个 std::string 可能是值得的合并所有数据,并使用 std::string_view在 map 中。这消除了互斥量争用,因为只需要一个内存分配。 string_view有一个简单的析构函数,所以你不需要线程。

    我以前成功地使用过这种技术将程序加速了 2500%,但这也是因为这种技术减少了总内存使用量。

    关于c++ - 在一个线程上删除具有数百万个字符串的大型 HashMap 会影响另一个线程的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60429872/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com