glibc 1.22 malloc(ptmalloc2)+ Poco(1.5.2)ThreadPool =非常慢?

时间:2015-10-28 20:04:57

标签: c++ linux multithreading memory-management poco

代码使用Poco HTTPServer(+ ThreadPool)来处理多个线程中的REST请求(minThreads = 16,max = 128)。

该框有12个CPU,并处理请求'意味着通过网络与DB或其他节点通信,因此事实#threads> #cpus似乎很合理。

此外,每个此类请求都涉及JSON处理,并且通常非常重要。但是,服务器是无状态的并且不保留缓存,因此,当服务器空闲时,内存消耗必须非常低。

现在,在长时间多客户端加载(测试之间暂停)之后,我会观察服务器性能开始下降的情况。例如,在开始时,每秒有大约300个HTTP请求,具有8个并行客户端。运行一天后,它会在完全相同的请求中显示每秒60-80-100个请求。没有数据被更改,请求是只读的。

此条件是永久性的,直到服务器重新启动,然后性能恢复正常。内存消耗是合理的,没有观察到内存泄漏。

花了很多时间后,我设法弄清楚了以下几点:

1)单线程负载不会降级

2)多线程负载:malloc()内部发生了降级 - 我使用了Linux' perf'看看大部分时间花在这里:

<....removed...>
-   39.22%    39.22%         SoLoader
   - _spin_lock
      - 55.86% futex_wake
           do_futex
           compat_sys_futex
           sysenter_dispatch
         - 0xb775f420
            - 87.48% operator new(unsigned int)
               + 27.60% std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&)
               + 11.59% operator new[](unsigned int)

这告诉我在分配上存在很多争议。当服务器“慢”时,大量的上下文切换速率也证实了这一点。与服务器快速&#39;,

相比

3)快速重启&#39;播放MALLOC_ARENA_MAX = 1服务器提供了几乎相同的“缓慢”行为。服务器

这让我得出结论,在我的加载模式下,Poco ThreadPool线程创建/保留/删除策略+ glibc malloc线程到竞技场分配启发式一起导致所有(或大多数)Poco工作线程时的退化情况(在池中)映射到相同的malloc竞技场。此映射发生在由线程生成的第一个malloc上,并保留线程的生命周期。当并行加载发生时,这些工作者争夺malloc()。这可以通过重新启动来修复,并在长时间加载后再次缓慢发生。

重申:我有32位服务器进程,12-cpu框,我观察服务器进程中的24个竞技场(匹配竞技场的malloc()文档)。竞技场大小非常不均匀。这个过程中有很多线程,大多数是空闲的,Poco配置为最少16名工人。测试通常作为8个并行客户端向服务器发出短请求,但有时并行级别可以是16甚至更高。经过15-60秒的测试,服务器空闲时会暂停。

问题是:有没有人遇到过这样的问题?这种降解有哪些可能的解决方案?

我已经尝试过TCMalloc,它似乎有所帮助,但看起来并不像解决方案(出于非技术原因)。我不知道glibc malloc()是否容易受到线程负载......

0 个答案:

没有答案