TinyWebServer
TinyWebServer copied to clipboard
reactor模式的效率比模拟preactor模式的效率低吗?
在reator模式中,IO读写是多线程并行的, 但是模拟preactor模式中,IO读写都是在主线程中串行完成的, 按道理说,并行reactor会更快才对。
但是从参考的运行结果看,reactor并没有明显的性能优势,这是为什么呢? 是收到了测试环境的影响吗? 还是IO读写在整个过程中占比很小,并不是耗时的大头?
同问
同问
同问
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
同样的看法,感觉这样写的确是会把主线程阻塞在ebServer::dealWithRead这里了,完全没有体现出线程池的作用。
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢
真心提问:为什么理论上说模拟的proactor会比reactor慢呢,模拟proactor中主线程是异步线程,按理说应该至少不会比多个reactor并行慢呀。 等个大佬解释一下。
真心提问:为什么理论上说模拟的proactor会比reactor慢呢,模拟proactor中主线程是异步线程,按理说应该至少不会比多个reactor并行慢呀。 等个大佬解释一下。
本人也不大懂,我的理解是因为proactor里IO任务都交给主线程串行执行,而IO任务一般是非常慢的,这样的话新的连接到来了也没法被及时处理
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢
我直接删掉了,结果网页可以正常运行,但是webbench压测的Requests一直为0,pages/min也为0,但是bytes/sec正常,不知道什么原因
找到原因了,注释掉读事件的循环之后工作线程会吧improv置为1,但是主线程的循环被注释后会导致iimprov绝大部分事件为0,之后在读事件之后才能为1。这就导致写事件很可能在工作线程没有写完之前就跳出循环了,没有结束连接,又因为webbench的模拟的请求都是短连接,在写事件完成应该关闭连接才能够算是一次事件,这样就造成压测的结果异常。
想要解决这个问题,应该把主线程判断工作线程io操作的这个逻辑让工作线程自己完成。
找到原因了,注释掉读事件的循环之后工作线程会吧improv置为1,但是主线程的循环被注释后会导致iimprov绝大部分事件为0,之后在读事件之后才能为1。这就导致写事件很可能在工作线程没有写完之前就跳出循环了,没有结束连接,又因为webbench的模拟的请求都是短连接,在写事件完成应该关闭连接才能够算是一次事件,这样就造成压测的结果异常。
good work!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢 我觉得修改的话需要把原本主线程执行的逻辑挪到线程池模块,比如关闭连接和删除定时器。但是这里的Webserver类是包含线程池的头文件的,如果threadpool中的工作线程需要调这个定时器删除逻辑的话,应该引入Webserver的头文件,然后把Webserver对象传入。但是这样会造成头文件循环依赖相互包含,我想的是把Webserver类维护定时器的职能拆分出来独立为一个模块,然后Webserver和threadpool同时包含他的实例化对象,让工作线程读完之后自己判断是否删除定时器以及关闭连接。主线程只负责监听事件即可。
我觉得这个reacotor之所以这样写很大可能是因为作者偷懒了,先写的模拟proactor。在这个框架上写reactor,所以职能区分的有些问题,但是可以省很多功夫。因为模块之间耦合的比较严重,修改的话不符合开放封闭原则,容易牵一发动全身。
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢 我觉得修改的话需要把原本主线程执行的逻辑挪到线程池模块,比如关闭连接和删除定时器。但是这里的Webserver类是包含线程池的头文件的,如果threadpool中的工作线程需要调这个定时器删除逻辑的话,应该引入Webserver的头文件,然后把Webserver对象传入。但是这样会造成头文件循环依赖相互包含,我想的是把Webserver类维护定时器的职能拆分出来独立为一个模块,然后Webserver和threadpool同时包含他的实例化对象,让工作线程读完之后自己判断是否删除定时器以及关闭连接。主线程只负责监听事件即可。
我自己的项目HAHA-WebServer,是参考别人的做法,把evenloop单独抽出来,定时器部分直接交给eventloop,相关的删除操作则是由webserver对象对eventloop注册回调函数去完成,这样就不耦合了
我觉得这个reacotor之所以这样写很大可能是因为作者偷懒了,先写的模拟proactor。在这个框架上写reactor,所以职能区分的有些问题,但是可以省很多功夫。因为模块之间耦合的比较严重,修改的话不符合开放封闭原则,容易牵一发动全身。
确实,作者应该也是知道这些问题,可能单纯不想改把
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢 我觉得修改的话需要把原本主线程执行的逻辑挪到线程池模块,比如关闭连接和删除定时器。但是这里的Webserver类是包含线程池的头文件的,如果threadpool中的工作线程需要调这个定时器删除逻辑的话,应该引入Webserver的头文件,然后把Webserver对象传入。但是这样会造成头文件循环依赖相互包含,我想的是把Webserver类维护定时器的职能拆分出来独立为一个模块,然后Webserver和threadpool同时包含他的实例化对象,让工作线程读完之后自己判断是否删除定时器以及关闭连接。主线程只负责监听事件即可。
我自己的项目HAHA-WebServer,是参考别人的做法,把evenloop单独抽出来,定时器部分直接交给eventloop,相关的删除操作则是由webserver对象对eventloop注册回调函数去完成,这样就不耦合了
已经star ^-^
我觉得reactor模式代码有问题。代码中将读事件插入阻塞队列中后有一个while(true)循环一直等到线程从阻塞队列中取此http链接后接受数据后才break。相当于阻塞队列中永远至多有一个http连接。
请教老哥觉得怎么修改才合理,能不能直接删掉这个while呢 我觉得修改的话需要把原本主线程执行的逻辑挪到线程池模块,比如关闭连接和删除定时器。但是这里的Webserver类是包含线程池的头文件的,如果threadpool中的工作线程需要调这个定时器删除逻辑的话,应该引入Webserver的头文件,然后把Webserver对象传入。但是这样会造成头文件循环依赖相互包含,我想的是把Webserver类维护定时器的职能拆分出来独立为一个模块,然后Webserver和threadpool同时包含他的实例化对象,让工作线程读完之后自己判断是否删除定时器以及关闭连接。主线程只负责监听事件即可。
我自己的项目HAHA-WebServer,是参考别人的做法,把evenloop单独抽出来,定时器部分直接交给eventloop,相关的删除操作则是由webserver对象对eventloop注册回调函数去完成,这样就不耦合了
已经star ^-^
多谢捏,这是我瞎写的项目,主要为了应付秋招的^-^
@huboy-zhao 奇怪了~我测试是删掉读事件的while后正常,只有删掉写事件的while之后,webbench测试才会出现你说的这种情况?
我对项目做了修改,将webserver的部分职能移到了httpconn 模块。删除掉了Reactor模式的while循环阻塞,改为在子线程中结束连接,但是压测结果没有太大提升,可能是因为webbench的请求方式的原因,io的耗时太短。有兴趣的可以看看 https://github.com/huboy-zhao/MyWebserver
我对项目做了修改,将webserver的部分职能移到了httpconn 模块。删除掉了Reactor模式的while循环阻塞,改为在子线程中结束连接,但是压测结果没有太大提升,可能是因为webbench的请求方式的原因,io的耗时太短。有兴趣的可以看看 https://github.com/huboy-zhao/MyWebserver
想请教一下,如果线程池中的线程也可以结束连接,删除定时器。那么从定时器堆(链表)中删除定时器就可能是race condition, 可能就需要锁了。但是原代码的实现是只有主线程才能删除定时器,所以不存在并发问题。不知道我的理解对不对。
我对项目做了修改,将webserver的部分职能移到了httpconn 模块。删除掉了Reactor模式的while循环阻塞,改为在子线程中结束连接,但是压测结果没有太大提升,可能是因为webbench的请求方式的原因,io的耗时太短。有兴趣的可以看看 https://github.com/huboy-zhao/MyWebserver
你好,请问你这里压测结果没有太大提升指的是修改后的reactor相比于原来的reactor没有提升,还是说相比于proactor没有太大提升,就是具体结果是哪一种最好呢?因为这里我也有同样的疑问所以请教一下。
真心提问:为什么理论上说模拟的proactor会比reactor慢呢,模拟proactor中主线程是异步线程,按理说应该至少不会比多个reactor并行慢呀。 等个大佬解释一下。
proactor里面读数据没有使用异步aio_read(),似乎是同步读取的。
你们觉得代码中的注释proactor和reactor没有问题吗?怎么看出来下面的m_actormodel==1时是reactor,等于0时是proactor?我感觉搞反了吧,proactor不是异步的通过回调函数处理的吗?reactor是等待IO结束后同步处理的,我理解的对吗?
void WebServer::dealwithwrite(int sockfd)
{
util_timer *timer = users_timer[sockfd].timer;
//reactor
if (1 == m_actormodel)
{
if (timer)
{
adjust_timer(timer);
}
m_pool->append(users + sockfd, 1);
while (true)
{
if (1 == users[sockfd].improv)
{
if (1 == users[sockfd].timer_flag)
{
deal_timer(timer, sockfd);
users[sockfd].timer_flag = 0;
}
users[sockfd].improv = 0;
break;
}
}
}
else
{
//proactor
if (users[sockfd].write())
{
LOG_INFO("send data to the client(%s)", inet_ntoa(users[sockfd].get_address()->sin_addr));
if (timer)
{
adjust_timer(timer);
}
}
else
{
deal_timer(timer, sockfd);
}
}
}