UDP – 微爆期间丢失的数据

下面的代码运行很好(即不丢弃消息)99.9的时间。 但是,当数据报之间以2-3微秒的速率进入数据报时,我会遇到数据丢失的情况。 boost notify_one()成员调用需要5到10微秒才能完成,所以在这种情况下本身就是关键的瓶颈。 有关如何提高性能的任何build议?

接收器/“生产者”代码线程:

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); } 

只是改变

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

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

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

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

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

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

你明显的堵塞是在调理。 你的主要希望是在使用无锁Q实现。 这可能是对你的一个明显的陈述。 当然,真正解决无锁问题的唯一方法就是如果你有多核心,并且不介意专注于消费任务。

一些一般的建议:

  • 增加套接字接收缓冲区大小
  • 读取所有可用的数据报,然后将它们全部传递进行处理。
  • 避免数据拷贝,通过指针。
  • 将锁定范围降低到绝对最低限度,比如说,只需将指针推入/弹出该互斥锁下的队列就可以了。
  • 如果以上所有都失败了,请查看无锁数据结构来传递数据。

希望这可以帮助。