UDP - 在微爆流期间丢失数据

时间:2011-07-12 19:44:00

标签: c++ windows boost boost-asio

以下代码在99.9的时间内运行良好(即不丢弃消息)。但是当数据报之间以2-3微秒的速率进入数据报微爆时,我就会遇到数据丢失。 boost notify_one()成员调用需要5到10微秒才能完成,因此在这些条件下,它本身就是关键的瓶颈。关于如何提高绩效的任何建议?

Receiver /“producer”代码线程:

if (bytes_recvd > 0) {
    InQ.mut.lock();
    string t;
    t.append(data_, bytes_recvd);
    InQ.msg_queue.push(t);    // < 1 microsecs
    InQ.mut.unlock();
    InQ.cond.notify_one();    // 5 - 10 microsecs
}

消费者代码主题:

//snip......
std::string s;
while (1) {
    InQ.mut.lock();
    if (!InQ.msg_queue.empty()) {
        s.clear();
        s = InQ.msg_queue.front();
        InQ.msg_queue.pop();
    }
    InQ.mut.unlock();
    if (s.length()) {
        processDatagram((char *)s.c_str(), s.length());
        s.clear();
    }
    boost::mutex::scoped_lock lock(InQ.mut);
    InQ.cond.wait(lock);
}

4 个答案:

答案 0 :(得分:2)

只需更改

if (!InQ.msg_queue.empty()) {

while (!InQ.msg_queue.empty()) {

这样数据包不必唤醒线程进行处理,如果线程已经处于唤醒和忙碌状态,它将在睡眠前看到新数据包。

好吧,它不是那么简单,因为你需要释放数据包之间的锁定,但这个想法会起作用 - 在睡觉之前,检查队列是否为空。

答案 1 :(得分:1)

如果丢失数据,请尝试增加套接字缓冲区读取大小。如果您正在使用boost :: asio,请查看以下选项:boost::asio::socket_base::receiver_buffer_size。通常,对于我们的高吞吐量UDP应用程序,我们将套接字缓冲区大小设置为1MB(在某些情况下更多)。

另外,请确保您在接收调用中使用的缓冲区不是太大,它们应该足够大以处理您的最大预期数据报大小(这显然取决于实现)。

答案 2 :(得分:1)

你明显的堵塞是在调理。 您的主要希望是使用无锁Q实现。这可能是一个明显的声明给你。 当然,真正让无锁q为你工作的唯一方法就是你有多核并且不介意专注于消费任务。

答案 3 :(得分:0)

一些一般性建议:

  • 增加套接字接收缓冲区大小。
  • 阅读所有可用的数据报,然后将它们全部传递下来进行处理。
  • 避免数据复制,传递指针。
  • 将锁定范围减小到绝对最小值,例如,只将指针推入/弹出该互斥锁下的队列。
  • 如果以上所有方法都失败了,请查看无锁数据结构以传递数据。

希望这有帮助。