- 主题:觉得协程不是一个太好的编程模型
这个没法限制,有些应用递归多。
当你做一个框架时,没办法限制应用插件怎么个用法。
【 在 finlab 的大作中提到: 】
: 现在服务器内存都上T了, 内存不是大问题。
: 大家在开发时,可以尽量对线程设置较小的栈空间。更好满足需要就好。
: 另外,有意识节省栈的使用,不要放大对象在栈上。
: ...................
--
FROM 221.218.60.*
数T的内存和上千核的服务器,不少见。
但是多用于云服务商。中小企业要租用CPU和内存,节约CPU和内存的使用,依然有意义。
【 在 finlab 的大作中提到: 】
: 现在服务器内存都上T了, 内存不是大问题。
: 大家在开发时,可以尽量对线程设置较小的栈空间。更好满足需要就好。
: 另外,有意识节省栈的使用,不要放大对象在栈上。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
测试过,在4核机器上,一百多计算密集型线程,性能下降明显。
在核数的1~2倍范围内,调度开销不明显。
【 在 hgoldfish 的大作中提到: 】
: 现代操作系统也没那么弱鸡。1K 个线程就算全忙也就那样。
: 写这种类型的程序,尽量不要陷入内核才是王道。只要不陷入内核,操作系统每隔 10ms 切个时间片,一秒也就切 100 次。约等于零开销。
:
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
我的例子,20G内存,难道不是64位?
20年前我们就进入64位时代啦,现在根本不考虑32位系统。
【 在 hgoldfish 的大作中提到: 】
: 看我上面提到的 mmap(MAP_STACK),平时我都是给我的栈设置至少 8MB 的。如果递归调用多,设置成 1GB 都不是事。用到才会真正分配。
: 已经 64 位时代了大哥们!
: 以前你们用 32 位机受到内存空间只有 2GB 的限制用不上这好东东。现在可以普及了。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
看我前边的内容。
总的设计,线程池的线程数保持在核数或2倍以内,不会发生可观的调度开销。
其余的就是架构设计的问题。
一个大并发的服务器,每个客户端连接一个context,连接后在epoll里排队。N个线程在epoll_wait。当所有线程忙起来之后,多余的请求在epoll里排队等待。这就已经能够充分利用核的能力,而且没有太大的线程调度开销。这么点线程,栈开销也不是问题。一切都非常完美,没有协程什么事。
正在得意之中,问题来了:
SendNet(bank,支付请求);
RecvNet(bank,银行回复);
你不知道银行何时回复。线程在这里死等。
多来几个这样的任务,不多的几个线程就全搁这儿了,别人排队等着吧。
那么就想,是否能让任务在这里等待,释放线程让它给别人干活去呢?想了好久。
看过协程那些例子,切换来切换去的,没啥意思,也没联想到我这个需求,直到有一次看到ASIO, 不就是它嘛!
【 在 finlab 的大作中提到: 】
: 协程调度同样有开销。
: 不过现在硬件线程切换核心的成本确实太高。 除了线程切换本身,切换后核心缓存作废影响也很大。
: 所以要硬件和操作系统一起想办法。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
看你的架构设计。
如果采用线程池,线程一经创建,永不销毁,就没有创建销毁的开销。
线程数等于核数,也不会发生调度,调度开销可以忽略不计。
线程池的调度机制,我用epoll,没事干的线程都在epoll_wait ,有事件出来干活,没事就在那儿待着,永不销毁。
前端有客户端,有需要服务器处理的数据,通过socket发过来,就会有一个线程被激活,接收数据并处理。
有很多客户端有事就有好几个线程处理,epoll有点像银行的排队机。线程像是服务窗口。
【 在 chaobill 的大作中提到: 】
: 那么线程调度的开支呢?
: 我现在理解协程
: 但对于线程却困惑了。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
协程的目的是用一个线程处理多个连接。
多线程的目的是利用多核的并行能力。
我的目的是二者都要,就是多线程协程。
多线程协程的服务器,加上带热插拔的动态模块管理,可以随时往服务器里添加处理模块。
【 在 z16166 的大作中提到: 】
: 啊,还有人在用32位的系统当服务器吗?哈哈
: 你这个是具体的应用,ylh1969搞的是一个能跑多个应用的平台,考虑的东西不同
:
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
在一个应用模块里,使用了IO,就可能在IO后换线程。
如果没有IO,就可以一直运行下去,不受打扰,没有调度开销。
【 在 z16166 的大作中提到: 】
: 您的同一个协程,有跨线程执行吗?
:
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
我的方案是交易中间件,所有的客户与商家(服务器)做交易(远过程调用,RPC),客户间没有联系,所以不能做游戏。
【 在 z16166 的大作中提到: 】
: 您的同一个协程,有跨线程执行吗?
:
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
我的协程栈是mmap分配的,向下生长。
线程池和协程栈尺寸一样,由配置文件决定。
函数调用桢就在栈里呀。
每个连接一个协程,10000个链接就10000个协程,但是不分配它栈。直到收到远过程调用的请求才分配它栈,调用完成收回。在远过程中间有IO调用的话,就会使用这个栈进行yield-resume。
【 在 hgoldfish 的大作中提到: 】
: 这个是 go, java 这些语言的做法。
: 我感觉你的实现是有 BUG 的。我记得你会迁移协程的内存,而不是使用我说的 mmap(MAP_STACK). 这样会导致引用到栈的指针出现问题。这是 c/c++ 在实现协程(纤程)时特有的问题。
: go, java 不需要使用 mmap(MAP_STACK) 的原因是因为他们其实并不使用栈,底层实现是 stackless 是一种编译期的变换,而是使用的函数调用帧,这东东其实是存堆里的。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*