内存 SPIKE - 提升 ASIO 异步读取

Posted

技术标签:

【中文标题】内存 SPIKE - 提升 ASIO 异步读取【英文标题】:Memory SPIKE - Boost ASIO ASYNC read 【发布时间】:2011-11-26 03:19:34 【问题描述】:

编写了一个只从客户端读取数据的服务器:

使用 boost::array 缓冲区

启动服务器,系统监视器显示 1MB 的使用量。

1.) 只需执行 async_read_some 并执行 handleRead,在其中我再次调用 asyncRead 函数。

void asyncRead() 
    m_socket->async_read_some(
        boost::asio::buffer(m_readBuffer, READ_BLOCK_SIZE),
        m_strand->wrap(boost::bind(&ConnectionHandler::handleRead,
                                   shared_from_this(),
                                   boost::asio::placeholders::error,
                                   boost::asio::placeholders::bytes_transferred))
    );

在 handleRead 中,我验证是否有任何错误,如果没有,我只需发出另一个 asyncRead()。

2.) 不断发送帧(数据大小约为 102 字节)。

在 10000 帧测试结束时。总发送大小 = 102*10000 总读取大小 = 102*10000

但是,系统监视器中的内存使用量高达 7.8 Mb。

无法找出这种增加的原因。尝试的不同方面是: 1.) 正在建立的连接数 - 只有 1 个。 2.) 已验证连接关闭 - 是的。 3.) 甚至停止了 ioservic 但仍然没有变化。

在第二次运行客户端时,我看到内存在增加。可能是什么情况?我正在使用 boost::array ,它是一个堆栈变量,只是读取。没有其他地方正在初始化缓冲区。

【问题讨论】:

您是否尝试过使用像valgrind 这样的内存泄漏分析器? 是的。问题在于在池中创建和维护的连接处理程序对象的状态重置。因此,当我们从池中取出旧对象时,我们最终会导致其中一个资源发生泄漏。 @Raja:听起来您的问题与您发布的任何代码都无关。也许你应该修改这个问题或删除它。 【参考方案1】:

拉贾,

首先,您是否知道 async_read_some 并不能保证您将阅读整个 READ_BLOCK_SIZE?如果您需要该保证,我建议您改用 async_read。

现在,回到最初的问题,你的情况很典型。所以,基本上,你需要一个容器(数组)来保存数据直到被发送,然后你需要摆脱它。

我强烈建议您切换到 boost shared_array。你可以像 boost 数组一样使用它,但是它有一个内置的引用计数器,所以当不再需要对象时会被删除。这应该可以解决您的内存泄漏问题。

【讨论】:

以上是关于内存 SPIKE - 提升 ASIO 异步读取的主要内容,如果未能解决你的问题,请参考以下文章

Boost asio - 从标准输入异步读取已建立的字符数

boost::asio 从 /dev/input/event0 读取

提升 async_read 不使用 ssl 读取所有数据

异步读取 inotify 描述符失败

boost asio 异步等待条件变量

提升asio断网处理