最近和同事聊起来,觉得lua缺乏编译型语言的类型校验功能,还有变量拼写检查之类的,导致线上总是有低级错误出现。比如最近有一个是变量名拼写少了一个字母,导致某功能没开启;还有一个是变量传参时,之前测试多加了一个参数,测试完成后忘记删了,导致参数顺序不对。之前看过有个TypeLua,没想到现在已经不怎么维护了,去搞了Titan-lang,然而Titan也是4个月没动静了。。。

目前也没想到什么好的解决办法,于是顺带看看Rust-lang,开阔一下思路。我最佩服rust这帮人的,是他们有点壮士断腕的勇气,已经写好的runtime和协程,认为和rust的定位不妥,就直接砍掉了。相关的PR在这里rfcs在这里。rfcs里面关于协程、线程模型的讨论相当到位,我简要翻译一下,权当记录。以下是译文(节译):

背景:线程/任务模型和I/O

很多语言/库会提供任务,任务一般有别于操作系统的原始线程。任务的特性可以按以下几个维度区分:

  • 1:1 vs M:N 最根本的问题是一个任务是不是总是对应到一个OS级别的线程(1:1模型),或者是通过用户空间调度器,将任务映射到worker线程上(M:N模型)。有一些内核,比如Windows,支持用户空间调度的1:1模型,结合了这两者的优势。

在M:N模型里,关于任务何时或者是否在worker线程迁移,各自有不同的选择。但是这个模型有个弊端,如果其中一个任务触发了page fault,整个worker线程都会被阻塞。选择合适的worker线程数目是非常困难的,有些框架尝试动态分配线程数,这也会产生额外开销。

  • 栈管理。在1:1模型里,任务就是线程,天然具有栈。在M:N模型里,任务可能有他们自己的栈,这里有重要的取舍:

    • 分段栈(segmented stacks)允许栈随着时间增长,意味着任务可以有自己的栈,而且依然保持轻量。但是,分段栈有明显的性能问题和复杂度开销
    • 在没有自己的栈的情况下,任务要么无法在工作线程间迁移(例如Java框架里的fork/join),或者只能用CPS(continuation-passing style)实现,即每个阻塞操作都用一个闭包保存自己的工作状态。(CPS一般将用到的栈保存在闭包里)好处是这些任务特别轻量,基本只是闭包的开销。
  • 阻塞和I/O支持。在1:1模型里,一个任务可以被任意阻塞而不会影响其他任务,因为每个任务都是一个OS线程。在M:N模型里,OS的阻塞意味着工作线程的阻塞(比如运行较长时间的循环,或者page fault)M:N模型可以用数种方法解决阻塞。在Java的fork/join框架下,是透过动态增减工作线程来实现的。另一种实现,是提供特殊的任务阻塞操作(包括I/O),将阻塞操作化作底层的非阻塞操作,允许底层工作线程继续运行。但是,这种实现只能对显式阻塞起作用,对于循环、page fault之类的就无效了。

Rust的现状

Rust从绿色线程模型(即协程模型)转向了原始线程模型:

  • 在Rust的绿色线程模型里,任务是按M:N进行调度,有自己的栈。最初,Rust使用了分段栈,后面改成了预分配的栈,这样Rust的绿色线程就不是轻量级的了。对阻塞的操作下文再叙
  • 在Rust的原始线程模型里,任务是1:1的和OS线程匹配的。

(节略)

问题

强制的共同演进:绿色线程模型和原始线程模型必须提供相同的I/O接口,但是有部分接口只会在其中一种模型里有效。比如,轻量级

开销:目前的Rust模型允许运行时将绿色线程模型和原始线程模型混合使用。但是实现上有如下缺点:

  • 二进制大小。任意二进制文件里都包含了整个I/O系统的实现,因为他是libstd标准库的一部分。
  • 任务局部存储。目前的任务局部存储是可以无缝在原始线程和绿色线程间切换的。但是性能会有影响,即使可以改进,也比直接采用原始的线程局部存储要复杂得多。
  • 动态分配和调度。当前的设计下,所有I/O操作都需要动态调度,大部分的内存分配操作也是。但是,绝大部分情况下,

问题重重的I/O交互:

嵌入式的Rust:

维护困难:

Rust对协程的思考的更多相关文章

  1. flask之分析线程和协程

    flask之分析线程和协程 01 思考:每个请求之间的关系 我们每一个请求进来的时候都开一个进程肯定不合理,那么如果每一个请求进来都是串行的,那么根本实现不了并发,所以我们假定每一个请求进来使用的是线 ...

  2. 协程的原理(Coroutine Theory)

    原文链接:https://lewissbaker.github.io/2017/09/25/coroutine-theory This is the first of a series of post ...

  3. Flask 之分析线程和协程

    目录 flask之分析线程和协程 01 思考:每个请求之间的关系 02 threading.local 03 通过字典自定义threading.local 04 通过setattr和getattr实现 ...

  4. python之协程与IO操作

    协程 协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B ...

  5. [转载]Python 3.5 协程究竟是个啥

    http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...

  6. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  7. Python 中的进程、线程、协程、同步、异步、回调

    进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说 ...

  8. 关于协程的学习 & 线程栈默认10M

    先看的这篇文章:http://blog.csdn.net/qq910894904/article/details/41699541 以nginx为代表的事件驱动的异步server正在横扫天下,那么事件 ...

  9. 深入tornado中的协程

    tornado使用了单进程(当然也可以多进程) + 协程 + I/O多路复用的机制,解决了C10K中因为过多的线程(进程)的上下文切换 而导致的cpu资源的浪费. tornado中的I/O多路复用前面 ...

随机推荐

  1. ASCII码表收藏

    ASCII码表 ASCII码值 ESC键 VK_ESCAPE (27)回车键: VK_RETURN (13)TAB键: VK_TAB (9)Caps Lock键: VK_CAPITAL (20)Shi ...

  2. 如何下载Twitter视频?最简单的保存推特视频的方法

    Twitter上面的短视频越来越流行了,但是推特官方并没有提供下载通道.如果你想下载这些小视频到电脑或者手机(安卓/iPhone),该如何操作呢?下面介绍一种最简单的方法. 下载Twitter视频我们 ...

  3. log4j日志打印的配置文件简单使用

    log4j.properties #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 log4j.rootLogger=DEBUG,c ...

  4. 09. Go 语言并发

    Go 语言并发 并发指在同一时间内可以执行多个任务.并发编程含义比较广泛,包含多线程编程.多进程编程及分布式程序等.本章讲解的并发含义属于多线程编程. Go 语言通过编译器运行时(runtime),从 ...

  5. Orcl分页查询的语法示例

    Orcle分页查询SQL sql =  SELECT T.* FROM (SELECT X.*, ROWNUM AS RN FROM (SELECT * FROM +表名) X WHERE ROWNU ...

  6. 激活函数-Activation Function

    该博客的内容是莫烦大神的授课内容.在此只做学习记录作用. 原文连接:https://morvanzhou.github.io/tutorials/machine-learning/tensorflow ...

  7. C#基础知识1-深入理解值类型和引用类型

    C#值类型和引用类型这个概念在刚学习的时候应该就知道了.但是我们并没有深入的去理解它.越是基础知识其实才是最有用的.对代码的优化,代码质量的提升都有帮助.通过整理本文章,对很多知识也起到了巩固的作用吧 ...

  8. 常用类-excel转csv

    public class ExcelFileHelper { public static bool SaveAsCsv(string excelFilePath, string destination ...

  9. Selenium(十二):操作Cookie、调用JavaScript、HTML5的视频播放

    1. 操作Cookie 有时候我们想要验证浏览器中cookie是否正确,因为基于真实cookie的测试是无法通过白盒和集成测试的.WebDriver提供了操作Cookie的相关方法,可以读取.添加和删 ...

  10. ES6新语法(一)

    1.常量         ES5没有定义声明常量的方式,ES6标准中引入了新的关键字const来定义常量.         常量必须给初始值: 常量不能在同一作用域内重新定义或赋值:  <scr ...