我有一个多线程系统,我有 x 个数量的线程同时向网络发送数据包。
这一切都适用于所有花花公子,但是我想限制其速度以便以一定速率发送数据包的一些线程。
所以我在我的数据包注入循环中进行了一次睡眠,它很慢地降低了线程的速度(1 Mbps到70Mbps左右),但是如果我想将它限制在1Gbps那么我就达不到这个速度随着睡眠到位。现在我知道它可以达到这个速度,因为如果我从所有线程中移除睡眠,它们可以以接近2Gbps的速度注入。
因此,作为测试,我用
替换了我的睡眠usleep(0);
我相信这应该能够使速度再次恢复到完全,但它仍然不会仍然有限(仅达到最大速度的约1/20)。所以我目前唯一的解释是,即使是睡眠(0),线程也会产生,因此没有一个线程获得足够的执行时间。
所以,对于长时间的解释感到抱歉,但有没有更好的方法来睡眠我的线程而不会造成这样的性能损失?
我已经尝试过,睡眠和纳米睡眠,两者都有相同的结果。所有测试的相同设置,即线程数
系统:CentOS,pthreads,g ++ 4.4.6
答案 0 :(得分:2)
考虑每注入sleep
个数据包添加n
次调用,而不是仅在每次迭代时添加。这样,您不会在每个注入的数据包上产生线程切换惩罚,并且您可以以相当细粒度的方式控制完成的睡眠量。
答案 1 :(得分:1)
可能是函数调用本身会降低速度(因为函数调用设置和拆除,或者因为调用中的某些东西正在做其他会减慢你速度的东西)。
您可能需要考虑以下行:
if (delay > 0) usleep (delay);
如果不需要延迟,则该函数不会被称为 。
你甚至可以将其封装成:
#define usleepIfNonZero(n) { if (n > 0) usleep (n); }
当然通常会对宏参数应用警告(不要传递像x++
这样的东西,否则你会发现它增加了两次)。
或者,只需保持数据包计数和用于计算的基准时间,并确定平均速度。例如:
#define PACKETS_PER_SEC 25
baseTime = now() - 1; // prevent divide by zero later on
packetCount = 0;
while (1) {
sendPacket (nextPacket());
packetCount++;
secondCount = now() - baseTime;
while (packetCount / secondCount > PACKETS_PER_SEC) {
sleep (1);
secondCount = now() - baseTime;
}
}
这将自动收敛到您的每秒数据包达到25的点,但当然您仍然发现处理不允许您达到全速。
答案 2 :(得分:0)
你说“所以我目前唯一的解释是,即使是睡眠(0),线程也会产生,因此没有一个线程获得足够的执行时间。”
根据http://pubs.opengroup.org/onlinepubs/7908799/xsh/usleep.html如果usleep(...)得到0,那么它没有影响所以,如果我们传递0就不会发生线程上下文切换!
你有没有验证我们睡觉(0);真的导致问题,如果你注释掉这个电话,一切都按预期工作了吗?
答案 3 :(得分:0)
不要以这种方式依赖睡眠来做节流。你不是一个实时系统。
而是发送X数据的突发,你想要发送X数据/时间单位,其中时间单位可能是ms或类似的东西。然后在发送每个突发数据后计算出你需要睡多少时间才能达到你想要的平均带宽并且睡得那么多。不要对最后一次突发进行计算,而是以高精度计时记录每个突发的开始时间,并计算在更大的突发集合上进行摊销,比如最后100次突发或类似的事情。通过这种方式,您可以平衡上下文切换,系统调用,主发送循环外部的任何开销,以及返回运行过程的延迟。
当你睡觉(x)(x!= 0)你正在屈服并且只是被添加到运行队列的某个地方时,无法保证你在非实时的情况下再次成为一个正在运行的进程的速度系统。因此,您必须随着时间的推移在开销中摊销这些差异。