yyzybb537 / libgo

Go-style concurrency in C++11
MIT License
3.21k stars 757 forks source link

测速效果不太理想? #226

Open dreamyphone opened 4 years ago

dreamyphone commented 4 years ago

写了以下demo的代码:

include

include

include”coroutine.h“

int main() { struct timespec start; clock_gettime(CLOCK_REALTIME, &start); go [start]{ struct timespec end; clock_gettime(CLOCK_REALTIME, &end); printf("%ld.%09ld\n", end.tv_sec - start.tv_sec, end.tv_nsec - start.tv_nsec); }; co_sched.Start(); }

在一台4.2GHz主频的机器上运行,耗时大约77微秒。
如果去掉go,耗时大约51纳秒。也就是go的运行消耗掉了大量的时间。
是我的代码写的有问题吗?

hnwyllmm commented 4 years ago

这个case对协程来说一点优势都没有。协程对多线程并发的提升不在于这种普通的计算,而是有大量io操作或者需要加锁同步时,能够减少上下文切换,进而提升性能。

dreamyphone commented 4 years ago

这个case对协程来说一点优势都没有。协程对多线程并发的提升不在于这种普通的计算,而是有大量io操作或者需要加锁同步时,能够减少上下文切换,进而提升性能。

我有个业务场景需要动态的添加协程, 如果增加一个协程需要耗时70微妙无法满足需求. 不知道有没有什么好办法可以快速动态增加协程

yyzybb537 commented 4 years ago

性能测试要看边际成本,你这样写,goStart函数中初始化逻辑占了大头。

yyzybb537 commented 4 years ago

另外,单次的go导致的空闲的调度线程被唤醒也是一个耗时的点,对于繁忙的调度线程就不会有这种损耗

dreamyphone commented 4 years ago

另外,单次的go导致的空闲的调度线程被唤醒也是一个耗时的点,对于繁忙的调度线程就不会有这种损耗

如此说来,如果要追求速度的话动态的去添加协程并不是一个好的做法是吗

sunny-shu commented 4 years ago

这个协程库跟java的线程池(ExecutorService)很像,就是只管提交要处理的任务,任务调度由框架来处理,维护一个任务队列,线程死循环去队列中获取任务进行处理。 有差异的地方是,这个库实现了一些原语,能让任务自己切换出去后,任务所在的线程能够处理其他任务;java的线程池没办法实现这一点,因为java目前没有机制能够保存上下文,让切除去的任务下次执行的时候,能够恢复现场,所以java处理一个任务的时候,任务必须处理完(函数返回),才能去调度其他任务。 任务里面的代码如果阻塞了,该条线程就会被阻塞,那样会失去设计协程的意义,退化成了线程池。所以作者对所有阻塞操作,单独设计了一套api,来防止这种退化。 个人认为这个库的协程,只是在多线程的基础上,模拟出了协程的特点,就像linux中的线程是在进程基础上模拟出来的。 @dreamyphone 协程一方面,利用多核提高并发性,来提高软件性能(非系统性能,CPU硬件资源是死的,只能提高利用率) 如果不利用多核的话,协程仅仅只是帮助你减少调度任务的代码而已。你的测试代码,只使用了单线程,对比直接跑这个函数,多了调度的开销,肯定会变慢呀。 @yyzybb537 我是加你qq的那位,初步浏览了下你的大作。我有理解不对的地方,多谢批评指正。

dylu6699 commented 3 years ago

可以添加我的QQ 805005062 吗?请教你个问题 @yyzybb537

dylu6699 commented 3 years ago

可以添加我的QQ 805005062 吗?请教你个问题 @hnwyllmm