Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于UnsafeSegManager疑似错误分配内存的问题 #26

Closed
YYHEggEgg opened this issue Jun 11, 2023 · 4 comments
Closed

关于UnsafeSegManager疑似错误分配内存的问题 #26

YYHEggEgg opened this issue Jun 11, 2023 · 4 comments

Comments

@YYHEggEgg
Copy link

YYHEggEgg commented Jun 11, 2023

由于我上次来提issue的时候似乎没有做好工作,因此这里先叠个甲:
我自己的上层协议栈与Kcp内部(Recv,循环调用Update)都保证了正确的单线程调用,保证这部分没有出现问题。
SingleThreadAssert.cs.txt


我正在做一点协议栈的测试工作,但是观察到了在测试发包压力巨大(10ms一次发包)的时候出现了严重的丢包。更确切地说,是包可能出现中间内容异位,或是包被掐头去尾(比较形象的描述)。

下面是两张现象截图(图中监视的是rcv_queue):

屏幕截图 2023-06-09 223519

屏幕截图 2023-06-09 232508

经过亿点点调试工作,最终确认了大概是使用了UnsafeSegManager的问题。

image

观察这幅图高亮的部分。Send 所使用的 KcpSegment 与 Input 中的一个 Segment 竟然共享一个 ptr,我不知道这是否是预期之内的情况。
这个包在 Flush 出口的时候被 Debug.Assert 拦下了,还没有 Flush 出去,应该不存在可能内存释放掉重用了的情况。再放一张 NEED_SEND 的日志证明一下:

image

切换到 SimpleSegManager 后没有出现过类似问题。PoolSegManager 没有测试过,主要因为它换了一个 Segment 类型,暂时不想做更多调试了。

@KumoKyaku
Copy link
Owner

不好意思,最近比较忙,今天才看见。
我初步理解了你描述的问题。

观察这幅图高亮的部分。Send 所使用的 KcpSegment 与 Input 中的一个 Segment 竟然共享一个 ptr,我不知道这是否是预期之内的情况。

UnsafeSegManager约等于非托管内存的内存池。共享一个 ptr 绝对是非预期的。
多线程情况下,池出现问题的可能性还是非常大的。
但是没有测试环境,仅分析代码,没有办法想出哪里可能导致这种这种情况。
我自己的测试用例,没有复现这个bug。

如果你有时间,可以尝试在free函数加锁,看看bug会不会消失。
image

@KumoKyaku
Copy link
Owner

另外,如果不执着于GC alloc,PoolSegManager 使用dotnet内置的内存池,可靠性比我手写的内存管理要可靠的多。
PoolSegManager 也不见得会多分配多少内存。

非托管内存更多用于GC洁癖的用户。

@YYHEggEgg
Copy link
Author

YYHEggEgg commented Jun 22, 2023

刚刚看见,试着上 Github Actions 跑了几次测试。先进行了几次测试:

  1. SimpleSegManager
  2. 原版 UnSafeSegManager
  3. Free() 加锁的 UnSafeSegManager

测试的标准都是 5ms 一发包,重复 10000 次,包大小 3500 字节。Windows 平台上和 Ubuntu 平台上各跑一次。
从宏观上来看,Windows 下 1、3都完全没有出现问题,2 出现了丢包(或是错包)。Ubuntu 这里都没有出现问题,可能因为速度比较快减少了并发压力。

(好像是说本地网络通信都是直接内存拷贝,因此速度极快,项目同一份代码放 Windows 下平均延迟 22ms,放到 Ubuntu 下可以达到 4ms)

然后改了一下标准,10ms 一发包,但是包大小上调到了 15000 字节。重复上面的 2、3 试验。

加锁后 3 仍然没有出现问题。2 在 Ubuntu 下似乎没有问题,但是在 Windows 下出现了更为严重的坏包,程序记录的丢包有大约 80%-90%(在我提 issue 的时候测试出来异常确实会积累,但是更有可能是我自己的代码写炸了解包出异常没有处理)

image

现阶段比较忙,并没有把 merge 之前带一堆测试符号的代码拿回来跑(应该连改个包大小都不一定适配了),但是就 Actions 上跑的这些数据我认为改完应该就没有什么问题了。

@KumoKyaku
Copy link
Owner

多谢。下个版本我会在free上加锁。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants