kcp
kcp copied to clipboard
what is the best practices with ikcp_check
I need to handle 10k connections, but ikcp_update consumes too much CPU. I know the ikcp_check is a better choice, but I don't know how to use it. I read all the issues and wiki, I found that many people have the same problem with me. If anyone knows how to use it, please answer here. a. If I use ikcp_check, do I still need to call ikcp_update repeatly ? b. Do I need to manually modify the value of kcp->updated ? Otherwise, the logic of ikcp_update and ikcp_check seems contradictory. c. If I use ikcp_check, do I need to increase the interval time ? Otherwise how does it achieve the effect of reducing the call (the return value of ikcp_check is shorter than interval). If anyone knows the answer, please tell me, thanks very much. I believe many people also need it !
Seems to me like you would want
While (1) {
Sleep(ikcp_check()); // which returns milliseconds to next update
Ikcp_update();
// handle input and output
}
But honestly I just read the code, haven’t started using Kcp yet.
对于C点, 我也有这个疑问, CHECK机制是怎么节省CPU的呢? 我测试的结果是interval是10毫秒时候, 依然在疯狂的update, 作者能回答下这个问题吗?
ikcp_check 是返回下一次需要调用 ikcp_update 的时间(如果没有 ikcp_input 的话),简单点:
while (1) {
current = clock();
ikcp_update(current);
ts = ikcp_check();
Sleep(ts - current);
}
实际的话,你需要同时管理 N 个 kcp 对象的 ikcp_check 返回时间,放到 timer里调度:
- 如果到时间了,那么执行 ikcp_update,并且重新 check,确定下一次时间,放入 timer 调度。
- 如果有数据包 ikcp_input 进来了,那么 ikcp_update,再 check 重新调度。
这么简单。
我的疑问是: CPU为什么会节省? 以interval=10ms为例 你的写法: while (1) { current = clock(); ikcp_update(current); ts = ikcp_check(); Sleep(ts - current); }
我们服务器的写法, 没有使用ikcp_check(伪码) setTimer(10, ()=>{ current = clock(); ikcp_update(current); } )
你的写法里ikcp_check返回的结果不会超过10MS, CPU省在哪里呢
我疑问的来源是, 最佳实践中提到: “使用该方法,原来在处理2000个 kcp连接且每 个连接每10ms调用一次update,改为 check机制后,cpu从 60%降低到 15%” 我所不明白的是: 原来是10ms调用一次update, 难道加入check机制后会变成超过10MS一次吗,我看到的ikcp_check的源码返回值是不会超过一个interval的? 望指正
哇哈哈,也正是我的疑问,按照文档的说法根本不可能节省CPU。如果改成以下这样才有可能节省(但逻辑不一定正确,可以探讨):
while(10ms loop)
{
current = clock();
next = ikcp_check(current);
// !!重点!!
if(current == next)
ikcp_update(current);
}
这个我也感觉很奇怪. 从ikcp_check代码来看的确起不到降低CPU的作用
除非我代码是死循环不带延时的调用update, 那调用ikcp_check才能达到比之前的CPU占用低的目的, 如果我本身代码里面就有延时 10 ms, 那即使调用ikcp_check, 根据ikcp_check返回值我还是顶多只能sleep 10ms...................
有了 ikcp_check,interval 就不需要订到 10ms 那么小了,kcp 就变成 tickless 了,你用timer,将多个 kcp 对象的调度,均摊再 1 个 interval 里面,就是这个意思。
有了 ikcp_check,interval 就不需要订到 10ms 那么小了,kcp 就变成 tickless 了,你用timer,将多个 kcp 对象的调度,均摊再 1 个 interval 里面,就是这个意思。
@skywind3000 还是有些疑问:首先需要确定是一个timer处理所有连接,还是每个连接有自己的timer? 1、如果是一个timer处理所有连接,势必会造成连接串行遍历,如果连接数较多(如1万个),加上每个连接send/recv/update等方法都需要同步,会不会造成更大的延时?另外,这种方式下interval值也不可能设置得太大。 2、如果每个连接有自己的timer,这时每个连接就自己管自己,不必遍历了。如:interval设置为1秒,以后根据ikcp_check的返回值确定下次update的时间。 3、还有一个问题:如果ikcp_check返回值为当前时间,是不是要继续循环调用check/update直到返回值大于当前时间为止?
现状是没有任何ikcp_check的示例代码,如果有示例给大家参考的话相信疑问会少很多。
每个链接都有自己的一个 timer id,使用 linux 时间轮算法,O(1) 的时钟调度。
我自己的网络协议栈是公司代码,没法开源,请理解。
感觉有点纠结了,interval不能设置太长, 但这种机制必然有个问题, 太长不及时,太短无端耗费CPU。
Kcp这几个函数或者变量确实令人迷惑。 interval 似乎并不是真的是 interval,因为 似乎并不是控制外部时钟频率的,而是内部用来比对的一个阈值。 update和check到底如何配合使用也是个问题。 而且就目前来看kcp不是线程安全的,但是调用update和check似乎又必须要开个timer线程调用。 总之Kcp的理念是不错。不过要用好,还是需要了解更多的细节,并且需要自己搞不少轮子,摸索最佳实践。
有了 ikcp_check,interval 就不需要订到 10ms 那么小了,kcp 就变成 tickless 了,你用timer,将多个 kcp 对象的调度,均摊再 1 个 interval 里面,就是这个意思。
从ikcp_update代码来看, 只有current>=ts_flush才会调用ikcp_flush. 这样调用ikcp_check还有什么意义呢?反正ikcp_flush的调用间隔始终是interval时间啊。
试着回答一下楼上的问题, timer的触发事件改成动态的,减少了timer的触发次数,当没有input或者send时,可以等待较长时间再触发timer,就节省了cpu