最近和同事聊起来,觉得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. 《Web Development with Go》Mangodb查询collection内所有记录

    相当于select * from table; package main import ( "fmt" "log" "time" " ...

  2. 七、3Dslicer的坐标系

    一.参考博客 https://blog.csdn.net/Huadong_eddy/article/details/84988166

  3. Vue小练习 02

    用table标签渲染下面的数据, 最后一列为总分, 第一列为排名 scores = [ {name: 'Bob', math: 97, chinese: 89, english: 67}, {name ...

  4. 深入requests库params|data|json参数

    深入requests库params|data|json参数 一.params params:字典或者字节序列,作为参数增加到URL中.不仅访问URL,还可以向服务器携带参数. 简单来讲也就是说对于原来 ...

  5. php反序列化漏洞绕过魔术方法 __wakeup

    0x01 前言 前天学校的ctf比赛,有一道题是关于php反序列化漏洞绕过wakeup,最后跟着大佬们学到了一波姿势.. 0x02 原理 序列化与反序列化简单介绍 序列化:把复杂的数据类型压缩到一个字 ...

  6. 读书笔记_python网络编程3_(2)

    2.UDP 2.0.数据包表示较短的信息,大小通常不会超过几千字节,在浏览器与服务器进行会话/电子邮件客户端与ISP的邮件服务器进行会话时,这些独立而小型的数据包是如何组成会话的呢? 2.0.1.IP ...

  7. centos7.6 安装Mysql5.7

    #安装Mysqlwget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpmyum localinstall mys ...

  8. 学习笔记:Django开发网上教育平台(参考了慕课网的教学视频)

    第一步:进行环境的搭建(用到的IDE:pycharm  ,数据库为mysql.nacicat.编辑语言python3.7.以及自己配置的虚拟环境venvpy37) Django==2.2​ ​ 配置好 ...

  9. Cent OS6.5——网络配置

    1.已安装centos 系统,打开虚拟机,并开机进入centos系统 2.进行网络配置,必须先确认以下几个点: 2-1.网络适配器模式是否为NAT模式,点击虚拟机,选择设置 ——选择网络适配器,NAT ...

  10. linux 头文件路径

    linux 头文件路径 /usr/include