【问题标题】:boost 1.55 asio tcp cpp03 chat_server example memory leaksboost 1.55 asio tcp cpp03 chat_server 示例内存泄漏
【发布时间】:2016-01-13 17:09:13
【问题描述】:

我希望有人能告诉我在哪里进行调查...

我正在从 boost 运行 chat_server 示例

http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp

在 Visual Studio 2010、Windows 10 上,我从以下位置下载了 boost 二进制文件:

http://sourceforge.net/projects/boost/files/boost-binaries/1.55.0/boost_1_55_0-msvc-10.0-32.exe/download

我用一个脚本模拟了30个tcp客户端,基本上每个线程的行为:

  1. 连接到 tcp 服务器
  2. 开始循环
  3. 向 tcp 服务器发送消息
  4. 从 tcp 服务器接收消息
  5. 睡觉
  6. 返回步骤 2

奇怪的事实是当我使用 Windows 任务管理器来监控内存消耗时。 private working set 和 shared working set 列的数字在近 18 分钟内保持“稳定”,之后 private working set 的值开始每分钟增加近 5 MB。

所以我的疑问是:

  1. 以前有没有人见过类似的东西?
  2. 是什么原因造成的?

问候

【问题讨论】:

  • 我不明白为什么所有的双端队列实现似乎都无法处理......双端队列。我可能会悬赏这个问题,看看是否有人能提出解释。

标签: c++ sockets boost tcp


【解决方案1】:

服务器会保留聊天记录,但只保留“环形缓冲区”中的 100 条最新消息(实际上是 deque<chat_message>)。

确实与大量聊天的客户进行了测试:

(for c in {00..99}; do for a in {001..999}; do sleep .1; echo "Client $c message $a"; done | ./chat_client localhost 6767& done)

显示内存增加:

细分表明这是由于deliver 为_write_msgs_ 分配的,这也是一个队列。

3.4 GiB: std::deque<chat_message, std::allocator<chat_message> >::_M_push_back_aux(chat_message const&) (new_allocator.h:104)
3.4 GiB: chat_session::deliver(chat_message const&) (stl_deque.h:1526)

不过,它在逻辑上并没有增长,所以看起来会有一些不幸的行为。

让我们调查一下:

在总的测试运行中(如上所示),任何会话的最大写入队列深度为 60。

重新启动所有客户端后(无需重新加载服务器),队列深度会立即增加到 100,原因很明显(所有客户端都会一次获得 100 个项目的完整历史记录)¹。

添加shrink_to_fit

在chat_session 中的每个pop_front 调用之后添加对shrink_to_fit 的调用不会使行为变得更好(除了c++03 当然没有shrink_to_fit 的事实)。

使用不同的容器

放入boost::circular_buffer 而不是std::deque,奇怪的是,队列深度很容易达到 100,即使在第一次运行时也是如此,但它确实改变了内存配置文件戏剧性地:

显然,将 deque 用作...一个双端队列 o.O 有一些不理想的地方,这非常令人惊讶。我将尝试使用 libc++:

改用 libc++

有趣的是,std::deque&lt;&gt; 和收缩适应 libc++ 显示了不同的 - 仍然很糟糕 - 曲线。另请注意,它报告了不断增长的_write_msgs_ 队列深度。不知何故,它的行为真的很不一样……o.O


¹ 即使客户端也立即开始咯咯笑,队列深度没有超过 100 - 所以吞吐量仍然很好。

【讨论】:

  • 我找到了罪魁祸首,并找到了一个可以解决问题的简单替代品。还在看livecoding.tv/sehe
  • 旁注:没关系,不断增长的队列深度是一种观察者效应(在 massif 内存分析器下运行会减慢它的速度,足以建立未传递的消息)。
  • 总结:deque 似乎不合适(libc++ 和 libstdc++ 以及 Boost Container 的 deque&lt;&gt; 中的 std::deque)。使用shrink_to_fit 似乎并没有真正改变任何东西。使用boost::circular_buffer 可以让其他任何东西都脱胎换骨——gcc 比看起来更准确一些。旁注:在不影响被分析的过程的情况下,分析仍然很棘手。
  • 录制我的努力的直播,以防你想偷看我的肩膀:livecoding.tv/video/why-is-asios-chat-sample-leaking-memory(大约开始于 ~27:00 标记)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
  • 2013-03-18
相关资源
最近更新 更多