免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: codechurch

[C] 寻求建议,关于异步编程 [复制链接]

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-05-29 11:17 |显示全部楼层
windoze 发表于 2015-05-25 15:01
回复 79# yulihua49

我晕,4个月过去了你又想起这出……

gcc -fsplit-stack a.c
cc1: 错误:无法识别的命令行选项“-fsplit-stack

况且,它只调整线程栈。协程栈能不能调还要看你自己。


这么长时间,不过是真正用于项目了,展现了问题。
现在问题已经找到,不需要那么多栈了。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-05-29 11:23 |显示全部楼层
回复 81# yulihua49

你用的什么系统?至少3年前的Linux/GCC4.7都是支持-fsplit-stack的。Fiberized.IO也支持,只要你打开了这个开关,fiber的stack就可以自动扩展。当然Boost也要打开这个开关重新build。

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2015-10-27 21:47 |显示全部楼层
讨论的很热烈, 我过来看一眼. Mark

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-09-23 06:20:00
发表于 2015-10-29 15:02 |显示全部楼层
本人用C语言在x86上实现了类似于C#的async await异步操作。
(windows使用setthreadcontext\getthreadcontext实现,linux用POSIX的ucontext.h下的函数实现。)
我已准备将其用于公司的项目。在此之前,我想听听各位的意见。这种做法在实现(网络)业务协议时非常方便,
不必维护“状态机”(自动机),而是在一个函数的流程里解决问题。但是,弊端呢? 除了浪费一点内存(我很快要移植到x64,我相信进程内存空间限制不是问题),
还有wp8的一点移植性问题,以及调试可能不太方便。除此之外的弊端还有什么?


以前没看到这个帖子,觉得有点想说的,针对原贴主。首先Windows上这么实现肯定是不行的,不是不能工作,是效率太差,还会有其他的问题。windows fiber也不好,不要用
ms自己都不用,只在早版本的sql server engine里面有过,不知道现在还有没有。coroutine也没什么用。async + message queue dispatch + ums(user mode scheduling)。

async_create() => create一个async task, 可以把它当成一个async io, 有个context, context 有 exec callack (相当于async_procedure).
async_post_work() => post work item to work queue, work queue pump the work item and dispatch to thread pool, work thread exec the work item
async_wait() => pump the message queue to check whether the work item is completed (whether context is posted back with result)

这里主要的问题是如果work item block 怎么办? coroutine 需要 work item YIELD, 对cpu bound的问题不大,如果work item 有io (尤其UNIX/LINUX 主要是sync io)
的话会block work thread, thread pool size会很大。setthreadcontext对一个pending在kernel的thread没用, 只对跑在user mode的时候有用,换句话说只在user mode cpu bound的
时候才有用。win7/2008 r2有个功能叫UMS(user mode scheduling), 在一个thread被block的时候 kernel会callback 你定义的一个函数,blocked thread 被release
之后,你会得到一个通知,你dequeue这个通知可以继续调度原先的work item。这是很关键的一点。普通coroutine被bind到一个thread之后,如果被block,你是没办法知道的。但是这仍然解决不了
被blocked的thread不能被利用的问题,有一个tricky的办法是拦截所有的blocking call, 转化成异步的syscall, 得到completion notification之后再调度到原来的work item, 可以以很少的thread支持大规模并发io,不管是同步还是异步。对原来的code,甚至第三方code完全透明。也不知道切不切题,啰嗦了不少。最近也在想这方面的问题。windows上可以利用concurrent runtime library(内部UMS支持)更方便。还有如果你suspend一个thread, 如果那个thread持有lock, 其他thread可以被block. 所以除非你非常清楚work item的code path,这是个危险的api.

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-10-29 15:26 |显示全部楼层
回复 84# irp

其实这事没什么特别好的办法,除了Windows上的UMS和(还没出来的)Linux上的User-Level Thread,能做的就是把所有可能会block的操作放到另外的thread里去跑。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-09-23 06:20:00
发表于 2015-10-29 15:46 |显示全部楼层
windoze 发表于 2015-10-29 15:26
回复 84# irp

其实这事没什么特别好的办法,除了Windows上的UMS和(还没出来的)Linux上的User-Level T ...


true. 所以并发的关键是任务分割。所以我觉得花时间去搞coroutine, 搞context switch无多大意义。尤其对network server 绝大多数是io bound, 如果不搞
async io 怎么摆弄都是徒劳的。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-10-29 16:02 |显示全部楼层
本帖最后由 yulihua49 于 2015-10-29 16:05 编辑
irp 发表于 2015-10-29 15:46
true. 所以并发的关键是任务分割。所以我觉得花时间去搞coroutine, 搞context switch无多大意义。尤其对 ...

对。只有其他油水都榨干了,最后来榨coroutine才有意义。
我现在就是别的都榨干了,任务分派,线程调度什么的都没油了。
现在的M:n基本稳定了。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-09-23 06:20:00
发表于 2015-10-29 16:10 |显示全部楼层
本帖最后由 irp 于 2015-10-29 16:26 编辑
yulihua49 发表于 2015-10-29 16:02
对。只有其他油水都榨干了,最后来榨coroutine才有意义。
我现在就是别的都榨干了,任务分派,线程调度什 ...

请问您什么work load要放到coroutine里面?我想来想去想不出coroutine和for ( i = 0; i < nr_req; i++) { exec_callback() } 有太大区别,除非为了平衡每个req的时间,即使如此,也不必要coroutine.
另外,我不知道您的程序allocator是不是lockless, 这在high work load下是主要的瓶颈之一。还有 io scheduler, 比如很多 request 访问的都是用一个文件,可以merge, 可以 scatter gather,
我看很多server都是直接一个syscall就完事。优化的空间肯定是很多的,内存管理和io scheduling是两个最大的可优化的主题之一。还有sheduling policy, 比如有的任务mark 成simple, 那么可以直接在
完成io的thread 调用,可以免除context switch, 可以得到cache locality.有的任务mark成may_block, 有的任务mark成urgent, 发包的时候不能delay, 有的是normal, 可以缓一缓等等。当然您的任务调度可能已经包含这些了。我没实现过,随便说点想法而已。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2015-10-29 21:05 |显示全部楼层
本帖最后由 yulihua49 于 2015-10-29 21:36 编辑
irp 发表于 2015-10-29 16:10
请问您什么work load要放到coroutine里面?我想来想去想不出coroutine和for ( i = 0; i < nr_req; i++) { ...

写了一大堆,论点比较散,不知先回哪个。
我们的协程是配合AIO/NIO的,一般场合并不需要切换。
m:n的协程,的确是有锁的问题。windoze是自己写了协程锁。我没有,我是禁止线程锁跨AIO。
在malloc的环节不切换协程所以锁无关。
目前数据库调用还不能AIO,所以锁暂时没问题。
前些日子有个贴说mysql可以AIO了,我还没试。
其他系统调用多是同步的,也不能切换协程。
我目前只有文件IO,通过两个函数:AIO_read和AIO_write是AIO+协程的封装,还有网络IO,net_send和net_recv是NIO+协程的封装。跨越他们的线程锁是不允许的。
也就是允许这4个函数的场合,线程可以逃逸,为别的任务服务。条件具备时会有某个线程resume。所以线程锁还是可控的。
将来可能还要写个A_usleep,进行异步定时。

协程,只为一些函数,看起来跟普通的函数没什么不同,内部确是切换了任务。在这个任务等待什么事件时,线程不耽误为别人服务。
线程的切换是极其有限的(尤其是那个NIO,是能不切就不切)。无谓的乱切换只能降低效率。你说的那么多状态,在我这多不存在。

所以我的协程是以epoll为核心的,epoll事件是resume的唯一条件。yield就是先安排好epoll事件,再swapcontext。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2015-10-29 21:36 |显示全部楼层
回复 86# irp

coroutine在这个场合不是为了优化性能,而是为了优化脑细胞耗损。

如果有人觉得node.js那样的回调套回调代码更易读,直接互略上一句就好了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP