【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

Code Like Sync, Works Like Async

  • 2020-10-20
  • 本文字数:2042 字

    阅读完需:约 7 分钟

Code Like Sync, Works Like Async

前言.

打从敲下"Hello World!",咱们算入行了。我开始写代码,和用计算器差不多:


  • 输入:1 + 1

  • 结果:2


代码一路顺着走,不开叉。


生涯第 1 个波折,是学到条件判断,像这样:


  • a = 1,b = 1

  • if a + b = 2 print "这都知道?"else print “答对了”


代码开始有不同走向,有点绕,还能驾驭。


再后来就遇到人生大哉问:妈和媳妇一起掉河里,你救谁?


翻译一下,如何同时运行代码 A 和代码 B(并行)?


为一起救,我学过各种泳姿:


  • 开始用 “定时器/软中断”挺好,不过随着媳妇数(代码块)的增多,猝!

  • 后来折腾“事件驱动/状态机”,就活在连跳/回调地狱里,最终为个 delay 而累猝!

  • 最后“多线程”还行…还活着。


焦头烂额,终于 hold 住。


可人生问题哪止这些,后来更大问题是 3 字:“没钱”


“多线程”虽好,太费钱(资源消耗大)、太折腾(竞争成本高),很多场景受限:


  • 浏览器:没有多线程

  • 嵌入式 MCU:实时性要求高、RAM 受限,甚至没有 RTOS

  • 大链接数 server:微信后台

  • 游戏:魔兽世界


吐血。


小品文已过,咱们言归正传。

1.

近些年,很多编程语言都修订标准,新增 2 个关键字 async/await:


  • 直接包含:C#/JavaScript/Rust/Dart

  • 其它语言(golang/erlang/lua…)没直接包含,也提供类似机制 ,比如 Go goroutine


所有目的,都是为更好的支持异步编程,不约而同的加强 Coroutine。


Coroutine(协程)是老东西(比 UNIX 都早),近些年的广泛使用有其背景:


  • 大量线程用不起(服务器或嵌入式),或者没有线程(浏览器或 MCU 裸机)

  • 然而,异步需求在,开源库 API 设计成异步 IO 渐变主流

  • 可异步代码太难搞,程序一膨胀,不是回调地狱就是全程乱跳。。。

  • 由此不约而同想:代码能不能写起来像同步,跑起来像异步?

  • 做梦之余一看,这不是就是 Coroutine 吗?好好,不止第三方库,要语言层支持,加 promise,再加 async/await


嗯,这段像瞎掰,实际是典型 JavaScript 开发者心态,其它也类似。


远的不说,做嵌入式开发,也常被异步 IO 编程(基于中断/消息/事件)搞得焦头烂额,我也想要“Code like sync, works like async”。


可 C/C++如何做 Coroutine 呢?

2.

方案 1


基于用户态 Scheduler(微信后台方案)


Coroutine 是简单的东西,第一反应就是拿用户态 Scheduler 实现。


即任务切换时,完成真实的换栈:



任务运行上下文(context)可以简视:寄存器/栈信息,当每个协程任务放弃(yield)时,执行 context 切换。看起来和 OS 线程没区别,实际是有的:


  • 所有 Coroutines 共享 1 个 CPU 线程,相互无抢占(协作式,竞争成本低)

  • Coroutine 更轻,尽管 Linux 中单线程只需约 4KB(1 页),然而 1 个 Coroutine 只 0.1KB

  • Coroutine 切换快(约 100T),在多数平台上消耗时间在纳秒级/微秒级


对大量链接的服务器后台,上述优势明显。可以参见腾讯开源协程库: libco。


这是对调用者干净的实现,编程没有限制,PC 端主流协程库都如此实现:


  • libco(微信)/Boost.Context(C++准标准)/libaco/coroutine


换栈的手段也不局限汇编,有系统库或第三方:


  • posix 中 context/Windows 中 fiber/C 标准中 setjump 等。


尽管如此,可对嵌入式编程意义很小:


  • RTOS 中 Task 实现类似,内存消耗/切换成本已经很低

  • RTOS 中 Task 亦可配置成协作式(非抢占)

  • 每种 CPU 都需要移植,等价于再实现 Scheduler,意义不大


方案 2


基于标签语法糖(switch 或 goto 扩展)


这是借用预编译宏和标签,大玩语法游戏的套路。


目前所有类似实现(如 Protothread),都基于 Simon Tatham 的文章,这里简要 1 种核心:



仔细看上述代码,它是合法的。在 switch/case 间,插入不同的语句,用不同 case 分割。由此换个视角看,count 可视为状态索引,每次进入时会恢复到代码对应位置。这是一种不基于换栈的任务切出/切回方式。


把上述 switch/case 手段用宏 crBegin/crFinish/crReturn 包装下,下面两段带 while(1)的死循环代码,就可以在 1 个线程中并发执行:



这是 Coroutine 实现的最轻方式,优点:


  • 完全标准 C 实现,跨平台

  • 每个 Coroutine 只需要额外 1 字节 - 2 字节内存

  • Task 切换无成本


不过,不知道大家发没发现,局部变量该怎么办?


没有换栈,无法用局部变量,必须 static 静态化。由此,这种方式受限明显:


  • 如果用 static 变量,会导致函数无法重入

  • 如果不用 static,就必须传参类似 ctx 参数来代替局部变量


看的出来,让调用者有些难受。


由此,Contiki OS 又对上述方法改良并包装,并用这种机制实现整个操作系统的多任务。


它的代码值得一读,除了这部分,其它模块(uIP/GUI/Timer/Mem)都很漂亮。

3.

大家看的出来,嵌入式系统上 1 和 2 还不够完美,有没有更好的方案?希望:


  • 只用 C99 实现,完全跨平台/跨架构

  • 内存消耗要远小于线程,额外消耗在几个字节内

  • 可以使用局部变量(至少表面上)

  • 对调用者友好,类似其它语言 async/await 的方式


显然需要新方案。


这里卖个关子,感兴趣的朋友可以留言讨论,请持续关注我们公众号哦~


作者介绍


王相宇,滴滴两轮车硬件技术部


本文转载自公众号普惠出行产品技术(ID:gh_ed6841067977)。


原文链接


Code Like Sync, Works Like Async


2020-10-20 14:002590

评论

发布
暂无评论
发现更多内容

支持M1/M2 Jump Desktop 8 Mac 远程桌面控制软件v8.10.4永久激活版

晴雯哥

IDC:用友再蝉联中国SaaS市场多项年度第一

用友BIP

企业服务

区块链积分商城系统开发

西安链酷科技

去中心化 dapp开发 #区块链

VUE为什么在中国如此流行?

Speedoooo

Vue 跨端框架 小程序容器技术 跨端技术

Zebec Protocol 薪酬支付工具 WageLink 上线,掀新一轮薪酬支付浪潮

BlockChain先知

从昏暗到明亮—改善照明环境,提升编程效率

颜淡慕潇

程序员 1024程序员节 明基BenQ ScreenBarBar

Zebec Protocol 薪酬支付工具 WageLink 上线,掀新一轮薪酬支付浪潮

威廉META

Parallels Desktop 19.1.0 最佳Mac虚拟机解决方案

晴雯哥

国际原油价格大波动,航司如何精准降低航油成本?

用友BIP

降本节能

简单好用的批量重命名软件:A Better Finder Rename 12 直装激活版

胖墩儿不胖y

Mac软件 重命名工具 重命名软件 文件重命名

室内LED显示屏和户外LED显示屏亮度标准

Dylan

屏幕亮度 LED显示屏 led显示屏厂家

思辨:移动开发的未来在哪?

巫山老妖

移动开发

2023版一线大厂Java面试八股文1000+ 面试题附答案详解,最全面详细!

架构师之道

编程 计算机 java面试

Python 数组和列表:创建、访问、添加和删除数组元素

小万哥

Python 程序员 软件 后端 开发

我们距离“裸眼3D自由”,还有多远?

脑极体

XR

极狐GitLab 致敬中国 1000万程序员

极狐GitLab

1024 极狐GitLab 致敬

ubuntu系统从源码编译安装gcc7.3.0编译器?

百度搜索:蓝易云

Linux ubuntu 运维 云服务器 GCC

Mac电脑文件批量重命名软件 Renamer 最新中文版

mac大玩家j

Mac软件 重命名工具 文件重命名

Linux绝对路径和相对路径

智趣匠

用友iuap数据中台又获奖了! 用友

用友BIP

数据驱动

Zebec Protocol 薪酬支付工具 WageLink 上线,掀新一轮薪酬支付浪潮

鳄鱼视界

CNCC 2023 | 五位重磅大咖齐聚沈阳,共同探讨「大模型与推荐系统」

小红书技术REDtech

人工智能 AI 算法 #推荐系统 #大模型

手把手带你打一场时间序列比赛—数据探索

打工人!

机器学习 时间序列预测

【Linux】进程间的通信之共享内存

百度搜索:蓝易云

Linux 云服务器 ipc Inter Communication

Java常见的锁及同步机制

echoes

Java基础面试题【Spring】二

派大星

Java 面试题 java 技术提升

Zebec Protocol 薪酬支付工具 WageLink 上线,掀新一轮薪酬支付浪潮

石头财经

Photoshop 2024 for Mac v25.1.0Beta 最新PS测试版多语言一键安装ACR 15.5.1 + Neural Filters + Ai创成式填充

晴雯哥

数划云与明道云达成产品战略生态合作

数划云

通过 Python 脚本支持 OC 代码重构实践(一):模块调用关系分析

百度Geek说

Python 自动化 重构 脚本 企业号10月PK榜

3D模型金属度怎么调?

3D建模设计

材质 纹理 金属度

Code Like Sync, Works Like Async_编程语言_王相宇_InfoQ精选文章