刚刚,阿里开源 iOS 协程开发框架 coobjc!

刚刚,阿里巴巴正式对外开源了基于 Apache 2.0 协议的协程开发框架 coobjc,开发者们可以在 Github 上自主下载。
coobjc是为iOS平台打造的开源协程开发框架,支持Objective-C和Swift,同时提供了cokit库为Foundation和UIKit中的部分API提供了协程化支持,本文将为大家详细介绍coobjc的设计理念及核心优势。


开源地址

https://github.com/alibaba/coobjc

iOS异步编程问题

从2008年第一个iOS版本发布至今的11年时间里,iOS的异步编程方式发展缓慢。

基于 Block 的异步编程回调是目前 iOS 使用最广泛的异步编程方式,iOS 系统提供的 GCD 库让异步开发变得很简单方便,但是基于这种编程方式的缺点也有很多,主要有以下几点:

  • 容易进入"嵌套地狱"
  • 错误处理复杂和冗长
  • 容易忘记调用 completion handler
  • 条件执行变得很困难
  • 从互相独立的调用中组合返回结果变得极其困难
  • 在错误的线程中继续执行(如子线程操作UI)
  • 难以定位原因的多线程崩溃(手淘中多线程crash已占比60%以上)
  • 锁和信号量滥用带来的卡顿、卡死

针对多线程以及尤其引发的各种崩溃和性能问题,我们制定了很多编程规范、进行了各种新人培训,尝试降低问题发生的概率,但是问题依然很严峻,多线程引发的问题占比并没有明显的下降,异步编程本来就是很复杂的事情,单靠规范和培训是难以从根本上解决问题的,需要有更加好的编程方式来解决。

解决方案

上述问题在很多系统和语言开发中都可能会碰到,解决问题的标准方式就是使用协程,C#、Kotlin、Python、Javascript 等热门语言均支持协程极其相关语法,使用这些语言的开发者可以很方便的使用协程及相关功能进行异步编程。

2017 年的 C++ 标准开始支持协程,Swift5 中也包含了协程相关的标准,从现在的发展趋势看基于协程的全新的异步编程方式,是我们解决现有异步编程问题的有效的方式,但是苹果基本已经不会升级 Objective-C 了,因此使用Objective-C的开发者是无法使用官方的协程能力的,而最新 Swift 的发布和推广也还需要时日,为了让广大iOS开发者能快速享受到协程带来的编程方式上的改变,手机淘宝架构团队基于长期对系统底层库和汇编的研究,通过汇编和C语言实现了支持 Objective-C 和 Swift 协程的完美解决方案 —— coobjc。

核心能力

  • 提供了类似C#和Javascript语言中的Async/Await编程方式支持,在协程中通过调用await方法即可同步得到异步方法的执行结果,非常适合IO、网络等异步耗时调用的同步顺序执行改造。
  • 提供了类似Kotlin中的Generator功能,用于懒计算生成序列化数据,非常适合多线程可中断的序列化数据生成和访问。
  • 提供了Actor Model的实现,基于Actor Model,开发者可以开发出更加线程安全的模块,避免由于直接函数调用引发的各种多线程崩溃问题。
  • 提供了元组的支持,通过元组Objective-C开发者可以享受到类似Python语言中多值返回的好处。

内置系统扩展库

  • 提供了对NSArray、NSDictionary等容器库的协程化扩展,用于解决序列化和反序列化过程中的异步调用问题。
  • 提供了对NSData、NSString、UIImage等数据对象的协程化扩展,用于解决读写IO过程中的异步调用问题。
  • 提供了对NSURLConnection和NSURLSession的协程化扩展,用于解决网络异步请求过程中的异步调用问题。
  • 提供了对NSKeyedArchieve、NSJSONSerialization等解析库的扩展,用于解决解析过程中的异步调用问题。

coobjc设计

最底层是协程内核,包含了栈切换的管理、协程调度器的实现、协程间通信channel的实现等。

中间层是基于协程的操作符的包装,目前支持async/await、Generator、Actor等编程模型。

最上层是对系统库的协程化扩展,目前基本上覆盖了Foundation和UIKit的所有IO和耗时方法。

核心实现原理

协程的核心思想是控制调用栈的主动让出和恢复。一般的协程实现都会提供两个重要的操作:

  • Yield:是让出cpu的意思,它会中断当前的执行,回到上一次Resume的地方。
  • Resume:继续协程的运行。执行Resume后,回到上一次协程Yield的地方。

我们基于线程的代码执行时候,是没法做出暂停操作的,我们现在要做的事情就是要代码执行能够暂停,还能够再恢复。 基本上代码执行都是一种基于调用栈的模型,所以如果我们能把当前调用栈上的状态都保存下来,然后再能从缓存中恢复,那我们就能够实现yield和 resume。

实现这样操作有几种方法呢?

  • 第一种:利用glibc 的 ucontext组件(云风的库)。
  • 第二种:使用汇编代码来切换上下文(实现c协程),原理同ucontext。
  • 第三种:利用C语言语法switch-case的奇淫技巧来实现(Protothreads)。
  • 第四种:利用了 C 语言的 setjmp 和 longjmp。
  • 第五种:利用编译器支持语法糖。

上述第三种和第四种只是能过做到跳转,但是没法保存调用栈上的状态,看起来基本上不能算是实现了协程,只能算做做demo,第五种除非官方支持,否则自行改写编译器通用性很差。而第一种方案的 ucontext 在iOS上是废弃了的,不能使用。那么我们使用的是第二种方案,自己用汇编模拟一下 ucontext。

模拟ucontext的核心是通过getContext和setContext实现保存和恢复调用栈。需要熟悉不同CPU架构下的调用约定(Calling Convention). 汇编实现就是要针对不同cpu实现一套,我们目前实现了 armv7、arm64、i386、x86_64,支持iPhone真机和模拟器。

Show me the code

说了这么多,还是看看代码吧,我们从一个简单的网络请求加载图片功能来看看coobjc到底是如何使用的。

下面是最普通的网络请求的写法:

下面是使用coobjc库协程化改造后的代码:

原本需要20行的代码,通过coobjc协程化改造后,减少了一半,整个代码逻辑和可读性都更加好,这就是coobjc强大的能力,能把原本很复杂的异步代码,通过协程化改造,转变成逻辑简洁的顺序调用。

coobjc还有很多其他强大的能力,本文对于coobjc的实际使用就不过多介绍了,感兴趣的朋友可以去官方github仓库自行下载查看。

性能提升

我们在iPhone7 iOS11.4.1的设备上使用协程和传统多线程方式分别模拟高并发读取数据的场景,下面是两种方式得到的压测数据。

  • 测试机器:iPhone7 iOS11.4.1
  • 数据文件大小:20M
  • 协程最多使用线程数:4
  • 数据测试结果(统计的是所有并发访问结束的总耗时):


从上面的表格我们可以看到使用在并发量很小的场景,由于多线程可以完全使用设备的计算核心,因此coobjc总耗时要比传统多线程略高,但是由于整体耗时都很小,因此差异并不明显,但是随着并发量的增大,coobjc的优势开始逐渐体现出来,当并发量超过1000以后,传统多线程开始出现线程分配异常,而导致很多并发任务并没有执行,因此在上表中显示的是大于20秒,实际是任务已经无法正常执行了,但是coobjc仍然可以正常运行。

我们在手机淘宝这种超级App中尝试了协程化改造,针对部分性能差的页面,我们发现在滑动过程中存在很多主线程IO调用、数据解析,导致帧率下降严重,通过引入coobjc,在不改变原有业务代码的基础上,通过全局hook部分IO、数据解析方法,即可让原来在主线程中同步执行的IO方法异步执行,并且不影响原有的业务逻辑,通过测试验证,这样的改造在低端机(iPhone6及以下的机器)上的帧率有20%左右的提升。

优势

简明

  • 概念少:只有很少的几个操作符,相比响应式几十个操作符,简直不能再简单了。
  • 原理简单:协程的实现原理很简单,整个协程库只有几千行代码。

易用

  • 使用简单:它的使用方式比GCD还要简单,接口很少。
  • 改造方便:现有代码只需要进行很少的改动就可以协程化,同时我们针对系统库提供了大量协程化接口。

清晰

  • 同步写异步逻辑:同步顺序方式写代码是人类最容易接受的方式,这可以极大的减少出错的概率。
  • 可读性高:使用协程方式编写的代码比block嵌套写出来的代码可读性要高很多。

性能

  • 调度性能更快:协程本身不需要进行内核级线程的切换,调度性能快,即使创建上万个协程也毫无压力。
  • 减少卡顿卡死: 协程的使用以帮助开发减少锁、信号量的滥用,通过封装会引起阻塞的IO等协程接口,可以从根源上减少卡顿、卡死,提升应用整体的性能。

总结

程序是写来给人读的,只会偶尔让机器执行一下。——Abelson and Sussman

基于协程实现的编程范式能够帮助开发者编写出更加优美、健壮、可读性更强的代码。

协程可以帮助我们在编写并发代码的过程中减少线程和锁的使用,提升应用的性能和稳定性。


#阿里云开年Hi购季#幸运抽好礼!
点此抽奖:https://www.aliyun.com/acts/product-section-2019/yq-lottery?utm_content=g_1000042901

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519667.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zookeeper 单机和集群搭建(windows环境+linux环境)

文章目录一、单机操作1. 下载2. 解压3. 修改配置文件4. 启动二、集群操作2.1. zoo.cfg添加集群配置2.2. 在3台zk数据目录下面创建myid文件2.3. 分别启动3台zk三、伪集群操作3.1. zk-01 配置3.2. 把zk-01复制2份3.3. zk-02配置3.4. zk-03配置3.5. 创建zk数据目录3.6. 在3个zk数据…

天线接收功率计算公式_对讲机天线到底有多重要?通信效果好不好全靠它了!...

天线是任何一个无线电通信系统都不可缺少的重要组成部分。各类无线电设备所要执行的任务虽然不同,但天线在设备中的作用却是基本相同的。任何无线电设备都是通过无线电波来传递信息,因此就必须有能辐射或接收电磁波的装置。所以,天线的第一个…

Java List集合转换相关操作

1、List转换为String字符串&#xff0c;并且指定分隔符 ArrayList<String> keyList new ArrayList<>();keyList.add("name");keyList.add("id");String keys StringUtils.join(keyList.toArray(), " , ");System.out.println(keys…

基于Blink构建亲听项目以及全链路debug项目实时响应能力

案例与解决方案汇总页&#xff1a;阿里云实时计算产品案例&解决方案汇总 本文全面总结了大数据项目组在亲听项目以及全链路debug项目上进行的实时流处理需求梳理&#xff0c;架构选型&#xff0c;以及达成效果 一、背景介绍 1.1亲听项目 亲听项目专注于帮助用户收集、展…

腾讯启动“SaaS技术联盟”联合行业制定互联互通标准

近日&#xff0c;腾讯宣布正式启动“SaaS技术联盟”&#xff0c;联合金蝶、用友、有赞、微盟、销售易、六度人和、道一、肯耐珂萨(KNX)等外部SaaS厂商&#xff0c;以及企业微信、腾讯会议、企点等腾讯内部SaaS产品共建技术中台&#xff1b;同时&#xff0c;工信部信软司相关领导…

WINDOWS 如何关闭3306端口

关闭windows中被占用的端口 1.查找到端口的PIDnetstat -aon|findstr "3306"TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING 4736 打开任务管理器

mysql innodb索引原理

聚集索引&#xff08;clustered index&#xff09; innodb存储引擎表是索引组织表&#xff0c;表中数据按照主键顺序存放。其聚集索引就是按照每张表的主键顺序构造一颗B树&#xff0c;其叶子结点中存放的就是整张表的行记录数据&#xff0c;这些叶子节点成为数据页。 聚集索…

jsp文字上下居中显示_微信朋友圈又有骚技巧,一键设置居中签名,好友傻眼了...

今日推荐&#xff1a;微信朋友圈签名居中适用&#xff1a;安卓、苹果大家好我是小雷&#xff0c;又来给大家安利微信小技巧了&#xff0c;今天给大家分享如何让你的朋友圈签名居中显示。熟悉微信的朋友都知道&#xff0c;在微信设置了个性签名之后&#xff0c;往往会同步到朋友…

云+X案例展 | 传播类:k3s基于逾百台工控机的应用实践

本案例由Rancher投递并参与评选&#xff0c;CSDN云计算独家全网首发&#xff1b;更多关于【云X 案例征集】的相关信息&#xff0c;点击了解详情丨挖掘展现更多优秀案例&#xff0c;为不同行业领域带来启迪&#xff0c;进而推动整个“云行业”的健康发展。随着国家政策的导向&am…

从大山走出的阿里首席通信科学家,这次要重返课堂

阿里巴巴首席通信科学家谢崇进与学生们交流 “我是一位没上过大学的科学家”&#xff0c;谢崇进在公益课堂上说。讲台下&#xff0c;是450位将要面临高考的乡村学生。 不久前&#xff0c;阿里巴巴首席通信科学家谢崇进通过网络视频的方式开课&#xff0c;向广东省汕头市潮南区…

MySQL 8.0.26 图形化安装教程 (windows 64位)

文章目录mysq8 比mysql5.7快2倍mysql8官网&#xff1a; https://dev.mysql.com/downloads/windows/installer/8.0.html 双击安装mysql-installer-community-8.0.21.0.msi

8s存储最佳方案_MaxiDi, 意大利:自动化物流解决方案

Maxi Di是Selex商业集团的成员&#xff0c;该集团在意大利拥有2500多家门店&#xff0c;是意大利最大的零售商之一。 由于公司的快速发展&#xff0c;其中央仓的存储容量很快面临饱和&#xff0c;公司不得不租用多个外部仓库以满足供应链的需求。 这导致高昂的租金成本以及库存…

程序员如何让自己 Be Cloud Native - 配置篇

前言 这是《程序员如何让自己 Be Cloud Native》系列文章的第二篇&#xff0c;从第一篇的反馈来看&#xff0c;有些同学反馈十二要素太形式主义&#xff0c;不建议盲目跟从。作者认为任何理论和技术都需要有自己的观点&#xff0c;这些观点是建立在个体知识体系逐渐锻炼出来的…

云+X案例展 | 传播类:南方报业数据中台建设,助力“智媒”飞跃发展

本案例由百分点投递并参与评选&#xff0c;CSDN云计算独家全网首发&#xff1b;更多关于【云X 案例征集】的相关信息&#xff0c;点击了解详情丨挖掘展现更多优秀案例&#xff0c;为不同行业领域带来启迪&#xff0c;进而推动整个“云行业”的健康发展。南方报业传媒集团在半个…

读取扫码枪输入_为何超市“扫码枪”这么强?不输密码钱就没了,现在知道还不晚...

点上面蓝色字免费关注!随着互联网的产生&#xff0c;我们的生活也发生了很大的变化&#xff0c;不仅变得更加便利&#xff0c;生活也变得丰富多彩一些&#xff0c;而有了网络之后&#xff0c;移动支付也应运而生&#xff0c;我们的支付方式也发生了很大的改变。如今只要携带一部…

助力深度学习!阿里开源可插拔 GPU 共享调度工具

根据 Gartner 对全球 CIO 的调查结果显示&#xff0c;人工智能将成为 2019 年组织革命的颠覆性力量。对于人工智能来说&#xff0c;算力即正义&#xff0c;成本即能力&#xff0c;利用 Docker 和 Kubernetes 代表云原生技术为 AI 提供了一种新的工作模式&#xff0c;将 GPU 机器…

使用maven 创建Quartz 任务示例_01

文章目录1. 创建maven项目2. 添加Quartz 依赖3. 编写Quartz配置文件4. 编写Job实现类5. 编写main函数&#xff0c;创建Scheduler6. 创建JobDetail7. 编写Trigger&#xff0c;添加JobDetail8. 启动main函数&#xff0c;体验Quartz定时任务Quartz 支持集群&#xff0c;但不支持分…

git commit提交代码时提示LF与CRLF转换问题 error

在用idea提交Vue项目的时候遇到报错&#xff0c;提示LF will be replaced by CRLF。 然后查了很多博客&#xff0c;都解释了LF和CRLF的问题&#xff0c;基本上说的解决办法是运行这行代码&#xff1a;git config --global autocrlf 运行结果为 true但这个本来就是默认设置&…

2019阿里云开年Hi购季大促主会场全攻略!

2019阿里云云上采购季活动已经于2月25日正式开启&#xff0c;从已开放的活动页面来看&#xff0c;活动分为三个阶段&#xff1a; 2月25日-3月04日的活动报名阶段、3月04日-3月16日的新购满返5折抢购阶段、3月16日-3月31日的续费抽豪礼5折抢购阶段。 整个大促活动包含1个主会场…

云+X案例展 | 民生类:肯耐珂萨入围腾讯SaaS加速器首期成员名单

本案例由肯耐珂萨投递并参与评选&#xff0c;CSDN云计算独家全网首发&#xff1b;更多关于【云X 案例征集】的相关信息&#xff0c;点击了解详情丨挖掘展现更多优秀案例&#xff0c;为不同行业领域带来启迪&#xff0c;进而推动整个“云行业”的健康发展。腾讯产业加速器新推出…