摸鱼精选第 1 期

1. Node.js 的底层原理

Node.js 主要是由 V8、Libuv 和一些第三方库组成。

其中 libuv 是异步任务的核心,本文探讨了 epoll 的模型与限制,无法读写文件、不适合 CPU 大量计算等操作,于是 Libuv 引入线程池解决这几个问题,最后作者梳理了 Libuv 的事件循环。

从三个方面介绍 V8:

  1. 介绍 V8 在 Node.js 的作用和 V8 的一些基础概念
  2. 介绍如何通过 V8 执行 JS 和拓展 JS
  3. 介绍如何通过 V8 实现 JS 和 C++ 通信

Node.js 中有五种模块加载器。

  1. JSON 模块加载器
  2. 用户 JS 模块加载器
  3. 原生 JS 模块加载器
  4. 内置 C++ 模块加载器
  5. Addon 模块加载器

2. 从根本上了解异步编程体系

作者从 CPU 调度的源头上开始梳理同步、异步的区别,异步的收益。

异步并不会让逻辑上串行的任务变快,只能让逻辑上可以并行的任务执行更快

异步操作离不开操作系统的底层支撑,目前三大 OS 都有自己实现机制,原理也不尽相同:

  • Linux: select、poll、epoll
  • Mac: kqueue
  • Windows: IOCP

Linux 的 epoll 的设计和性能都不如 windows 的 iocp,最新的 5.1 内核加入了 io_uring,算是向 windows 的 iocp 致敬了。

  • 为了让程序在同一时间内处理更多的请求,我们采用多线程。多线程虽然编写简单,但是对内存和 CPU 资源消耗大,因此我们考虑利用系统的异步接口进行开发;
  • 我不知道异步操作什么时候结束,只能不停的轮询它的状态。当有多个异步操作,每个的响应时间都未知,不知道该去先轮询哪个。我们利用操作系统提供的能力,把异步事件加入全局监听队列,然后通过 wait_until_some_of_them_get_ready 来等待任意事件就绪,所谓的 EventLoop;
  • 当事件就绪后 EventLoop 不知道该执行什么逻辑,只能进行一个非常复杂的判断才能确认后续逻辑该执行哪个函数。因此我们给每个异步事件注册回调函数,这样 EventLoop 的实现就高效而清爽了;
  • 所有异步程序都需要在最后执行 EventLoop 等待事件就绪然后执行回调,因此可以把 EventLoop 这块逻辑放到语言自身的 runtime 中,不需要每次自己写。
read_async_v2('qq.com', function (data) {
  send_to('pony@qq.com', data);
});
read_async_v2('jd.com', function (data) {
  write_to('jd.html', data);
});

// 编译器帮我们把while循环自动插到这里
// 或者什么异步框架帮我们做while循环

用回调来处理异步就会遇到“回调地狱”的问题,JS 为了解决这个问题引入 Promise 范式。作者从 0 开始梳理 Promise 的实现过程,遇到的问题以及解决办法。

关于 Linux io_uring 异步 IO 接口的资料:

3. Rust 是 JavaScript 基础设施的未来

Rust 在底层编程上有安全优势,但是并不是说只适合干 C/C++的活。上层应用方面现在也用的很多,尤其是做一些 cli 工具的时候。

4. RabbitMQ 七种消息传递形式

5. 彻底搞懂容器技术的基石: cgroup

6. Flutter 中 TextField 组件必然会遇到的问题

本文提到两个 TextField 需要注意的问题:字数统计和文字居中。

  • 在 iOS 的中文输入法下,由于拼音联想功能,点击字母,输入法会给出联想中文预览,但实际上用户还没有确认,所以 TextField 会计算正在编辑的拼音字母的数量,而不是实际的中文数量,这是不符合需求的。官方没有解决这个问题,但是作者通过一种巧妙的办法可以解决。

  • 文字居中可以通过修改InputDecoration里面的 contentPadding 字段达成,但是当 TextField高度有变化时,居中效果没有跟着变化,所以要动态计算高度。主要难点是计算出字体的高度,这里可以使用TextPainter来计算高度。

7. Flutter App 逆向工程 12