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

这里是不是有bug #31

Closed
dwxiayi opened this issue Oct 30, 2017 · 5 comments
Closed

这里是不是有bug #31

dwxiayi opened this issue Oct 30, 2017 · 5 comments

Comments

@dwxiayi
Copy link

dwxiayi commented Oct 30, 2017

bool UThreadEpollScheduler::Run() 中
业务线程开启协程时,epoll_wait可能会被业务fd唤醒,但handler_new_request_func_被注册,
就会被调用处理新请求,Worker::HandlerNewRequestFunc()函数中貌似是阻塞取io线程的消息的,这样的话业务中的其他协程就会暂时挂起,影响性能。
PS:从性能测试看,短连接、长连接的性能差距蛮大的,有没有考虑cache 协程的方案?
即:进程启动后就开启N个IO协程,当accept到连接时使用缓存的协程等待读,读取完数据不销毁协程;业务协程同理。

@unixliang
Copy link
Collaborator

unixliang commented Nov 1, 2017

bool UThreadEpollScheduler::Run() 中
业务线程开启协程时,epoll_wait可能会被业务fd唤醒,但handler_new_request_func_被注册,
就会被调用处理新请求,Worker::HandlerNewRequestFunc()函数中貌似是阻塞取io线程的消息的,这样的话业务中的其他协程就会暂时挂起,影响性能。

Worker::HandlerNewRequestFunc 里是用 ThdQueue::pick 来取消息的,这里并不会阻塞。

PS:从性能测试看,短连接、长连接的性能差距蛮大的,有没有考虑cache 协程的方案?
即:进程启动后就开启N个IO协程,当accept到连接时使用缓存的协程等待读,读取完数据不销毁协程;业务协程同理。

协程池是有的,可以看看UThreadRuntime :: Create,一开始会从context_list_中取空闲协程,而不是每次都创建新的。
协程任务完成后,UThreadRuntime :: UThreadDoneCallback会负责回收协程,塞回到context_list_

@dwxiayi
Copy link
Author

dwxiayi commented Nov 1, 2017

感谢回复,没有认真看代码,不好意思。
1.ThdQueue::pick确实是非阻塞,但是每次激活都要干这个事,感觉怪怪的,放在EpollNotifier :: Func()更好些吧
2.缓存我觉得libco中这个样例做的更好(https://github.com/Tencent/libco/blob/master/example_echosvr.cpp),业务层可以更多的cache资源,节省的底层调度,改造也非常简单。
3.
EpollNotifier :: Notify() 也许会有问题,socket的buffer不够用,通知失败,业务线程是一次通知取一次消息,有消息会未被取走,1中业务线程也会取到不该自己取的消息,ps请原谅我的强迫症,嘎嘎!

@dwxiayi
Copy link
Author

dwxiayi commented Nov 1, 2017

@unixliang
Copy link
Collaborator

1.ThdQueue::pick确实是非阻塞,但是每次激活都要干这个事,感觉怪怪的,放在EpollNotifier :: Func()更好些吧
3.EpollNotifier :: Notify() 也许会有问题,socket的buffer不够用,通知失败,业务线程是一次通知取一次消息,有消息会未被取走,1中业务线程也会取到不该自己取的消息,ps请原谅我的强迫症,嘎嘎!

1和3都提到了EpollNotifier,我合在一起说哈。
首先,worker收到通知后,并非一定要取触发了EpollNotifier :: Notify的那个数据包。数据包给哪一个worker处理都是一样的。
另外,EpollNotifier只是一个优化,即使没有EpollNotifier,也不影响数据包在IO层和worker层之间传递的。
EpollNotifier的作用是,在低吞吐场景下,减少单个请求的处理耗时。背景是,在无事件的情况下, epoll_wait即使传入的超时时间为0, 也会等待4ms左右,这可能会导致数据包从IO层传递到worker层中间卡4ms。这时候通过EpollNotifier来产生事件,可以让epoll_wait马上返回,避免这种卡顿。

2.缓存我觉得libco中这个样例做的更好(https://github.com/Tencent/libco/blob/master/example_echosvr.cpp),业务层可以更多的cache资源,节省的底层调度,改造也非常简单。

其实流程是一样的,都是协程完成任务后,将自己塞到一个 空闲协程列表 里;再有任务到来时,从列表里取空闲协程。

@dwxiayi
Copy link
Author

dwxiayi commented Nov 2, 2017

感谢解答,学到了不少,哈哈!

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