导语 | 本文推选自腾讯云开发者社区-【技思广益 · 腾讯技术人原创集】专栏。该专栏是腾讯云开发者社区为腾讯技术人与广泛开发者打造的分享交流窗口。栏目邀约腾讯技术人分享原创的技术积淀,与广泛开发者互启迪共成长。本文作者是腾讯后台开发工程师杨良聪。 协程(coroutine)是在执行过程中可以被挂起,在后续可以被恢复执行的函数。在C++20中,当一个函数内部出现了co_await、co_yield、co_return中的任何一个时,这个函数就是一个协程。 C++20协程的一个简单的示例代码:
导语 | 在c++20标准正式推出后,asio也对c++20 coroutine做了支持,虽然推出时间尚短,有一些不那么尽善尽美的地方,但其中的一些点还是值得我们学习的。asio最新版本的协程实现有两版,本文我们主要以作者在《Why C++20 is the Awesomest Language for Network Programming》中演示的那版来进行内容的展开。我们先从一个实际的使用示例出发,来逐步了解asio coroutine的整体设计。 一、asio协程的简单示例 大部分时候我们使用asi
作者:fangshen,腾讯 IEG 游戏客户端开发工程师 导语 本文我们将尝试对整个 C++的协程做深入浅出的剥析, 方便大家的理解. 再结合上层的封装, 最终给出一个 C++异步框架实际业务使用的一种形态, 方便大家更好的在实际项目中应用无栈协程。 1. 浅谈协程 在开始展开协程前, 我们先来看一下一些非 C++语言中的协程实现. 1.1 其他语言中的协程实现 很多语言里面, 协程是作为 "一类公民" 直接加入到语言特性中的, 比如: 1.1.1 Dart1.9 示例代码 Future<int> get
前面的文章中我们尝试从 C++17 和 C++20 的角度分别探讨过其中无栈协程的包装机制和使用, 但其中的设计由来, 原理, 剥析的并不多. 这也导致对相关特性不太熟悉的读者要理解相关内容存在比较大的成本. 本篇我们将更多的回归原理, 背后的设计, 尝试对整个C++的协程做深入浅出的剥析, 方便大家的理解. 再结合上层的封装, 最终给出一个C++异步框架实际业务使用的一种形态, 方便大家更好的在实际项目中应用无栈协程. PS: 本文的主要内容与IEG课程 <> 基本一致, 文字版细节更多, 更适合阅读.
前段时间我在实现 rust-kernel-riscv (使用 Rust 无栈协程进行上下文切换的操作系统内核) 时, 跟进了一些 Linux Kernel 的特性, 其中印象最深的就是 io_uring. io_uring 作为最新的高性能异步 I/O 框架, 支持普通文件与网络套接字的异步读写, 解决了传统 AIO 的许多问题. 在 Linux 通过隔离内核页表来应对 Meltdown 攻击后, 系统调用的开销是不可忽略的, 而 io_uring 通过映射一段在用户态与内核态共享的内存区域, 显著减少系统调用的次数, 缓解了刷新缓存开销. 关于 io_uring 的使用方法可以参考迟先生的博客: io_uring 的接口与实现.
[!info] 导语: 在先前的文章《从无栈协程到C++异步框架》中,我们探讨了如何将上层的协程调度器与底层的C++17协程实现以及C++20协程实现相结合,从而构建一个在单线程环境下易于使用的异步框架。通过相关示例,我们发现协程在表达线性类型业务方面具有显著优势。那么,在多线程环境下,当单个协程的执行不再受限于单一线程时,我们能否继续保持这种线性类型业务的友好表达,并在多线程环境中充分利用协程的优势呢?本篇文章将致力于解决这一核心问题。
如果你要在 WPF 程序中使用线程池完成一个特殊的任务,那么使用 .NET 的 API Task.Run 并传入一个 Lambda 表达式可以完成。不过,使用 Lambda 表达式会带来变量捕获的一些问题,比如说你需要区分一个变量作用于是在 Lambda 表达式中,还是当前上下文全局(被 Lambda 表达式捕获到的变量)。然后,在静态分析的时候,也难以知道此 Lambda 表达式在整个方法中的执行先后顺序,不利于分析潜在的 Bug。
点个关注👆跟腾讯工程师学技术 导语 | 本文我们将尝试对整个 C++的协程做深入浅出的剖析,方便大家的理解。再结合上层的封装,最终给出一个 C++异步框架实际业务使用的一种形态,方便大家更好的在实际项目中应用无栈协程。 浅谈协程 在开始展开协程前,我们先来看一下一些非 C++语言中的协程实现。 (一)其他语言中的协程实现 很多语言里面,协程是作为 "一类公民" 直接加入到语言特性中的, 比如: Dart1.9示例代码 Future<int> getPage(t) async {
上一章节介绍了协程的现状,并以libco为例介绍了主流有栈协程的实现原理。这一篇,我们开始进入C++20原生协程的研究。
导语 | 本篇文章循序渐进地介绍C++20协程的方方面面,先从语言机制说起,再来介绍如何基于C++20的设施实现一个对比C++17来说更简单易用,约束性更好的一个任务调度器,最后结合一个简单的实例来讲述如何在开发中使用这些基础设施。 Vue框架通过数据双向绑定和虚拟DOM技术,帮我们处理了前端开发中最脏最累的DOM操作部分,我们不再需要去考虑如何操作DOM以及如何最高效地操作DOM,但是我们仍然需要去关注Vue在跨平台项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。 一、C++20 Cor
在前文中我们介绍过了在C++17中怎么利用Duff Device特性Hack出一个无栈协程实现, 并基于这个无栈协程实现了一个任务调度器, 具体可参见 <<如何在C++17中实现stackless coroutine以及相关的任务调度器>>. 这篇文章算是本篇文章的前篇, 侧重于介绍C++17下无栈协程的实现, 以及任务调度器的实现, 对协程本身的应用展开的比较少. 本篇文章循序渐进的介绍C++20协程的方方面面, 先从语言机制说起, 再来介绍如何基于C++20的设施实现一个对比C++17来说更简单易用, 约束性更好的一个任务调度器, 最后结合一个简单的实例来讲述如何在开发中使用这些基础设施.
作者:fangshen,腾讯 IEG 客户端开发工程师 C++20带来了coroutine特性, 同时新的execution也在提案过程中, 这两者都给我们在C++中解决异步问题带来了新的思路. 但对比其他语言的实现, C++的协程和后续的execution都存在一定的理解和封装成本, 本系列的分享我们将围绕基本的原理, 相应的封装, 以及剥析优秀的第三方实现, 最终结合笔者framework落地的情况来展开. 1. 纠结的开篇 之前设计我们游戏用的c++框架的时候, 刚好c++20的coroutine已经
最近的新闻里 C++20 已经确认的内容里已经有了协程组件,之前都是粗略看过这个协程草案。最近抽时间更加系统性的看了下接入和实现细节。
如果您不熟悉 io_uring 和 c++20 协程,可以参考这个仓库里的其他一些文章和示例代码:
背景 基于跨平台考虑,微信终端很多基础组件使用 C++ 编写,随着业务越来越复杂,传统异步编程模型已经无法满足业务需要。Modern C++ 虽然一直在改进,但一直没有统一编程模型,为了提升开发效率,改善代码质量,我们自研了一套 C++ 协程框架 owl,用于为所有基础组件提供统一的编程模型。 owl 协程框架目前主要应用于 C++ 跨平台微信客户端内核(Alita),Alita 的业务逻辑部分全部用协程实现,相比传统异步编程模型,至少减少了 50% 代码量。Alita 目前已经应用于儿童手表微信、Lin
故事的开篇是笔者参与开发的一款自研引擎的底层 C++ 框架, 恰逢其时, 包含 stackless coroutine 特性的 C++20 已经发布并得到了几大主流 C++ 编译器的支持, 所以我们框架的异步模块实现也很自然的基于 stackless coroutine 的特性实现了一版工作在单一线程上的协程调度器, 对于一些依赖多次串行的异步操作来完成的业务逻辑来说, 这种机制确实带来了很大的便利, 你可以以非常线性的方式来对这种类型的业务逻辑进行实现了. 但美好总是短暂的, 很快我们就碰到了大量多线程相关的异步逻辑使用场景, 如FrameGraph里的DAG实现等, 完全依托Lambda Post机制, 肯定也是可以写的, 但相关的复杂度并不低, 这种情况下, 团队成员就开始考虑能否借助协程, 来简化相关代码的复杂度了. 这种情况下, 我们开始考虑以单线程版本的协程调度器实现作为基础, 尝试结合比较新的 C++ 异步思路, 来重新思考应该如何实现一个支持多线程, 尽量利用 C++ 新特性, 同时业务层简单易用的异步框架了. 问题的一部分答案我们其实在 <<从无栈协程到C++异步框架>>系列文章中给出了部分答案, 最后我们通过结合 ASIO 的调度器与 stackless coroutine, 以及来自 taskflow 的思路解决DAG相关的描述问题, 很大程度上已经解决了上面的问题. 但更未来向的 executions 在框架中的位置和标准化之后如何更好的利用它来进一步支持上对异步的结构化表达, 以及它与前面的Lambda Post, 多线程协程的区别和它的适用场景, 都是一个未来需要比较好的去回答的一个问题, 这也是本文主要想去探索解决的问题. 从本文最初成文(大概是2022年5月, 发布于公司内部KM和purecpp)到这次重新整理整个系列(2023年9月), 整个尝试的过程只能说一波三折, 并不是非常顺利了, 当然, 随着对相关实现的深入理解和细节的深挖, 收益也是颇多的. 闲话不多说了, 我们直接切入主题, 以笔者项目中对异步的实践和相关的思考来展开这篇总览的内容.
作者:peterfan,腾讯 WXG 客户端开发工程师 背景 基于跨平台考虑,微信终端很多基础组件使用 C++ 编写,随着业务越来越复杂,传统异步编程模型已经无法满足业务需要。Modern C++ 虽然一直在改进,但一直没有统一编程模型,为了提升开发效率,改善代码质量,我们自研了一套 C++ 协程框架 owl,用于为所有基础组件提供统一的编程模型。 owl 协程框架目前主要应用于 C++ 跨平台微信客户端内核(Alita),Alita 的业务逻辑部分全部用协程实现,相比传统异步编程模型,至少减少了 5
在讲协程之前,先回顾C11之前我们怎么处理多任务,怎么同步不同任务之间的处理顺序。想象一个你在用文本编辑器GUI,你对GUI的每个button进行操作,背后都有一段函数代码处理你的button事件。这就是事件驱动。事件驱动代码的一个典型示例是注册一个回调,每次套接字有数据要读取时都会调用该回调。
与其他编程语言相比,C++ 加入协程较晚,从C++20开始支持。在协程出现之前,C++ 程序员有两种选择:
在前文 1. 基于 c++ executions的异步实现 - 从理论到实践 中我们也提到过, 对于lambda post的一些缺陷, 在execution中都能够比较好的得到解决. 由于c++ execution目前还是PR状态, 并未正式发布, 但sender/receiver机制应该是得到了越来越多人的认可了, 也确实将C++的异步提到了一个新的高度. 这里我们选用高度符合标准提案, 能够实际测试, 并且test众多的libunifex来展开本篇的内容, 从libunifex上, 我们也能感受到sender/receiver模型带来的整个C++异步的改变, 以及他为何能够弥补lambda post的一些缺陷.
最近GCC 10.1.0 发布,三大编译器(MSVC、GCC、Clang)都已经支持了C++20协程,之前给 libcopp 接入 C++20协程 的计划也就提上了日程。C++20协程 在创建、切换开销和内存分配上和传统有栈协程相比有着无可比拟的优势。但是C++20全面普及还有相当长一段时间,所以我们设计的重要目标之一就是能够让以后的迁移更容易且更平滑地进行,本文则是记录了 libcopp 接入 C++20协程 时地一些性能上和平滑接入上的思考和成果。
导语 | 本篇我们将重点从libunifex介绍,感受sender/receiver模型带来的整个C++异步的改变,以及它为何能够弥补lambda post的一些缺陷,希望对这部分感兴趣的开发者提供一些经验和思考。 前言 在前文《C++异步从理论到实践!》中我们也提到过,对于lambda post的一些缺陷,在execution中都能够比较好的得到解决。由于c++ execution目前还是PR状态,并未正式发布,但sender/receiver机制应该是得到了越来越多人的认可了,也确实将C++的异步提到了
最近GCC 10.1.0 发布,三大编译器(MSVC、GCC、Clang)都已经支持了C++20协程,之前给 libcopp 接入 C++20协程 的计划也就提上了日程。C++20协程 在创建、切换开销和内存分配上和传统有栈协程相比有着无可比拟地优势。但是C++20全面普及还有相当长一段时间,所以我们设计的重要目标之一就是能够让以后的迁移更容易且更平滑地进行,本文则是记录了 libcopp 接入 C++20协程 时地一些性能上和平滑接入上的思考和成果。
c++20的协程学习记录(一): 初探co_await和std::coroutine_handle<>
最近开的坑有点多。有点忙不过来了所以好久没写Blog了。这个C++20的协程接入一直在改造计划中,但是一直没抽出时间来正式实施。 在之前,我写过一个初版的C++20协程接入 《libcopp接入C++20 Coroutine和一些过渡期的设计》 。当时主要是考虑到 Rust也有和C++类似的历史包袱问题,所以参考了一些Rust协程改造过程中的设计。 但是后来尝试在项目中使用的时候发现还是有一些问题。首先C++20的协程并不是零开销抽象,所以强行用Rust的模式反而带来了一定开销和理解上的难度。其次原先的设计中 generator 是按类型去实现外部接入的。但是实际接入SDK的过程中我们有相当一部分类型相同但是接入流程不同的情况,再加上现在各大编译器也都已经让C++20协程的特性脱离 experimental 阶段了,有一些细节有所变化。所以干脆根据我们实际的使用场景,重新设计了下组织结构。
我们终于在年初的时候最后完成了整体服务器框架对C++20协程的支持和接入。虽然之前陆陆续续抽时间改造一些组件,让它支持C++20协程,期间也记录了一些早期的设计思路和踩的坑(包括 《libcopp接入C++20 Coroutine和一些过渡期的设计》和《libcopp对C++20协程的接入和接口设计》),其中不乏一些C++20协程使用上可能打破我们常规思路细节和编译器的BUG。而且这些都是各个组件的改造,并没有最后整合到一起。
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
协程不是系统级线程,很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互快速切换
在 C# 中编写异步代码的时候,我们经常会选择将异步代码包含在一个 Task 或者 ValueTask 中,这样调用者就能用 await
https://cloud.tencent.com/developer/article/2375995
有一个东西叫做鸭子类型,所谓鸭子类型就是,只要一个东西表现得像鸭子那么就能推出这玩意就是鸭子。
之前写了 《协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比》 和 《C++20 Coroutine》 ,但是一直没写 C++20 Coroutine 的测试报告。
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
异步编程常用于网络请求、缓存数据加载、本地File图片加载、定时与延时任务等,在Flutter开发中 ,使用async开启一个异步开始处理,使用await来等待处理结果,如处理一个网络请求,代码如下:
博客园中有很多关于 .NET async/await 的介绍,但是很遗憾,很少有正确的,甚至说大多都是“从现象编原理”都不过分。
编译器信息最新动态推荐关注hellogcc公众号 上周更新 2023-03-29 第195期
异步IO(Asynchronous I/O)是一种并发编程的方式,它可以在等待某个I/O操作完成的同时,同时进行其他的操作,而不是一直等待I/O操作完成。异步IO是通过非阻塞I/O和事件循环来实现的。
众所周知,JavaScript 是单线程的,所以浏览器通过 JavaScript 发起的请求是异步请求。Python 自带的 asyncio 模块为 Python 带来了原生的异步能力。
协程是一种轻量级的线程,它允许我们在同一个线程内并发地执行多个任务。在协程中,我们可以使用 async/await 语法来定义异步操作。例如,我们可以使用 async def 定义一个异步函数,并在函数中使用 await 关键字来等待异步操作的完成。
异步编程是一种编程范式,它允许我们同时处理多个任务,而不必等待每个任务完成。在传统的同步编程中,我们通常是按顺序执行代码,一次只处理一个任务,直到完成后才继续执行下一个任务。而在异步编程中,我们可以同时处理多个任务,并在任务完成时处理它们的结果。
协程是一种轻量级的线程,它允许我们在代码中使用异步的方式进行并发处理。Python提供了async/await关键字来支持协程编程。
如果你了解过 JavaScript 的线程模型,那么就会明白当你遇到有延迟的运算时(请求),它的运行过程都是异步的,只有这样你的 Web 应用UI才不会出现明显的卡顿。在现实的网络世界里,多数情况下我们的业务都基于请求而展开的,Dart也是一个单线程的语言,因此在操作请求时它的运行过程也是异步,Dart.io 中封装了操作请求的类,你可以很便捷的使用它们。
在传统的同步IO编程中,当我们发起一个HTTP请求时,我们需要等待服务器返回响应,这样就会阻塞当前线程的执行。如果需要发起多个HTTP请求,就需要创建多个线程或进程来处理这些请求,这样会造成资源浪费和性能下降。为了解决这个问题,Python提供了异步IO编程模型,可以实现异步HTTP请求,从而提高程序的性能和并发能力。
对于爬虫程序,我们往往会很关注其爬虫效率。影响爬虫效率有几个因素有,是否使用多线程,I/O 操作,是否同步执行等。其中 I/O 操作、同步执行是最影响爬虫效率的。
Axios 是一个基于 promise 的 HTTP 库,它支持 Promise API。
在过去很长的一段时间里,JavaScript开发人员不得不依赖回调来处理异步代码。如果遇到赋值的逻辑,会发现,特别难处理维护,代码看起来也特别的糟糕。
网站应用程序主要分为两大部分:客户端和服务器端。 客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTML、CSS、JavaScript构建。 服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。
领取专属 10元无门槛券
手把手带您无忧上云