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

about the benchmark #38

Closed
zhengshuxin opened this issue Sep 6, 2020 · 6 comments
Closed

about the benchmark #38

zhengshuxin opened this issue Sep 6, 2020 · 6 comments

Comments

@zhengshuxin
Copy link

workflow 内部线程池的设计方式本身是有瓶颈的,其是一种常规的线程池设计模型,但当线程池中线程数较大时会因 pthread_cond_signal 的设计导致惊群问题(具体原因可以 man 一下 pthread_cond_signal 或 https://blog.csdn.net/zsxxsz/article/details/88388425 );
另外,与 nginx 的性能对比可能也存在问题,你们不妨把 nginx 的日志关闭再对比测试一下(我对比测试后发现nginx性能还是远高于workflow的)。nginx 因为其单线程非阻塞的设计方式,其CPU亲和性要远好于线程池的设计方式,其性能基本是随着CPU核数和进程数增加呈线性增长的,而 workflow 中的 demo 在线程数(其中的 pollers 和 handlers)到一定数时就无法再提升了,应该还是线程池中的锁碰撞和 CPU 亲和性等原因);
还有就是nginx的 HTTP 协议解析过程是规范的(从其对url的解析便可以看出),并且功能逻辑也是较为复杂的。

@Barenboim
Copy link
Contributor

Barenboim commented Sep 6, 2020

感谢ACL作者关注我们项目!
我先描述一下我们的nginx测试方法,我们是用固定大小本地文件来作为返回的数据。当然也试过在配置文件内指定返回内容,但实验性能没有区别,就简单的用了本地文件。log是开着的,但是打到了/dev/null。
好像我们各种nginx的测试里,一直没有绝对数字特别大的QPS结果,一般20多万就到头了(跨机)。你这么一说我们明天找一下各路nginx专家再做一些实验,之后再同步一下数据。
关于技术实现上的两个问题:
1、消息队列。这个我们做过不少实验,目前的方案是在最常规的方式上做了一点点优化,应该可以解决一些对consumer的惊群问题。极限性能大概每秒消费100w次左右,这个是我们单进程的qps上限,需要更高的话可以开多进程server。这块以后努力优化。
2、HTTP消息解析这块,因为这个实验只涉及到解析一个比较小的HTTP GET request,相信不太会影响实验结果。

项目刚开源,感谢大家的意见!

@zhengshuxin
Copy link
Author

感觉您的回复。单线程调度(如nginx, redis,irc之类的)服务程序一般CPU亲和性都会比较好,资源竞争也比多线程调度小的多,workflow 内部是多线程池之间的协作,性能能达到如此之高也确实非常不错了。另外,workflow 的代码写的比较干净整齐,也很值得大家去学习。
---zsx

@Barenboim
Copy link
Contributor

Barenboim commented Sep 7, 2020

经过组里同学的努力,参照您建议的做法,在C200的情况下nginx已经做到了29w+的QPS,workflow各种调也能上升一些。
但是,我们发现在C20K的情况下,nginx的QPS上升到55w+,单进程workflow(需要调参增加最大连接数)下降到29w+。所以现在单进程wf和nginx的QPS实验最大值都在55w+,但达到峰值的并发连接数不同。我们图表里选用的C200方法是对我们有利的一个参数。
接下来我们再给出更多连接数与QPS关系的数据。另外wf不支持http pipeline server,我们需要说明一下。
多进程wf server还没有详细实验,但在连接非常多的情况下比单进程更好。启动多进程server方法如下:

int main()
{
    WFHttpServer server(proc);
    int sockfd=socket(...);
    bind(sockfd, ...);
    // listen(sockfd, ...); // no need listen
    fork();
    fork();
    server.serve(sockfd);
    pause();
    server.stop();
    ...
}

以上代码启动一个4进程server。通过serve接口,还可实现精确的优雅重启(需要把stop拆解为shutdown+wait_finish)。
ACL的线程调度我在学习了。我们的是比较原始,但也是优化空间啊😁。再次感谢ACL作者大神!

@Barenboim
Copy link
Contributor

@zhengshuxin
更新了线程池。和ACL不太一样,但是有一些功能我觉的和ACL的thread pool还比较互补。例如在一个线程任务里,添加另一个任务(往往是一个相同的任务),我们这个不用考虑线程池是不是正在被销毁。这个功能对我们还挺重要的。
我们的线程池功能比较单一,主要还是解决Workflow系统本身的需求。最近的改动更是没有什么功能添加,都是往有趣了做:)

@Barenboim
Copy link
Contributor

惊群问题我们之前message queue模块实验过,方法和ACL的解决方案差不多,确实比普通消息队列在高QPS的时候优化很多。后来message queue用了更加简单粗暴的方法,就是读写用两个队列,读的时候把整个写队列交换走。这个方法的问题是在QPS不太高的时候,会多加一次锁。我其实更喜欢每个消费者在一个condition的方法。

@zhengshuxin
Copy link
Author

不错,每在都在进步,赞一个!

Barenboim pushed a commit that referenced this issue Mar 9, 2021
merge from sogou/workflow master
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