以下代码在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);
}
答案 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)
一些一般性建议:
希望这有帮助。