菜菜博士

博士在网络的家

福特和福建的弹射技术对比

电磁弹射,被加速的舰载机总重,30吨,即3万公斤;加速长度100米,加速时间2.2秒,舰载机末端速度,85米每秒;总耗电能38度;瞬间功率6万千瓦。 福特航母在上实际90年代立项。 上世纪90年代,哪家公司能拿出功率达到 6万千瓦的变频器和储能40度电的超级电容呢? 这就是有时候,先驱变成先烈的问题。 因为当年没有大功率的逆变器技术, 因为超大功率的逆变器是随着特高压直流输电才研发出来...

资本主义绝户计

全世界的文明,都陷入了一个困境:经济越是发达,生育率越低。 很多人说,这是因为经济发达了,妇女受教育程度高了。女性不愿意生孩子了。 这就是典型的胡说八道。但是这种错误认知居然还是当下的主流认知。 为什么说这个认知是错误的呢?女性接受教育就会自我阉割放弃生育权? 这个错误的离谱之处在于,否认了男性在抚养后代上的承担。仿佛孩子只要生下来就可以自动长大。 生孩子只要幸苦10个月,养孩子则要...

调用约定和上下文切换

编写协程库的时候,我常常在想,上下文切换的速度,受调用约定的影响非常大。 因为用户协程的上下文切换,本质上是调用一个 函数。而这个函数需要 “切换” 非易失性寄存器。 因此,在给定的调用约定下,非易失性寄存器越多,则上下文切换时需要保留和恢复的寄存器数量就越多。 而由内核进行上下文切换(也就是线程),所有寄存器都得保留。开销是最大的。何况还有执行特权级切换的巨大开销。 在知乎...

在Linux上交叉编译windows版 Qt 和 qt应用

准备工具链 一个半月前,我研究了一下 使用本机 clang 进行交叉编译。那时候,是在本机 x86 上交叉编译 arm 和 mips 架构的软件。目标系统还是 linux 的。 交叉编译,需要使用交叉工具链。而使用本机clang进行交叉编译,只是将交叉工具链里的“编译器”换成了本机本就安装的 clang, 而 “头文件和库文件” 则是使用 archlinux 和 mips debian ...

协程切换为什么需要 一个 hook_function 参数.

前言 刚刚,我将 zcontext 的 API 进行了以下修正。 从 void* zcontext_swap(zcontext_t* from, zcontext_t* to, void* argument); 改成了 typedef void* (*zcontext_swap_hook_function_t)(void*); void* zcontext_swap(zcont...

从0开始写上下文切换

有栈协程的核心是执行上下文。执行上下文的核心是栈。 因此,切换栈就等于切换了上下文。 栈在协程切换上的核心地位 栈,存储了一个协程/线程 的“调用链”,以及依附于这条链上的“变量”。 没有栈,ret 指令将无所适从。 虽说栈是核心,但是栈本质是堆叠存储“历史 寄存器状态”。而当前没有入栈的寄存器状态,才是真正的当前上下文。 因此,很多古代协程库的做法,是栈协程“句柄” 上,开辟一...

链接到 ucrtbase.dll

使用 vc6.0 以后的 VS 编译器,最恼火的一点就是生成的 exe 依赖 msvcrXXX.dll。 其中 XXX 是个版本号。而且 msvcrXXX.dll 系统是不自带的。 于是每个 exe 都得带上 vcredist.exe 安装程序。 过于蛋疼。 正统的解决方法是改使用静态C库。 但是会带来二进制体积暴涨的问题。 十分的怀念 VC6.0 可以生成exe 依赖 msvcr...

boost.fcontext 为何快?

在 批评 libco 的 上下文切换代码的时候,我曾经说,协程的上下文切换代码,并不需要恢复所有的寄存器。 只需要恢复调用约定里规定的 “非易失性寄存器”。 只有操作系统进行抢占式调度的时候,才需要恢复所有的寄存器。因为抢占式调度,可以在任何时间任何地方中断线程。如果不恢复所有寄存器,则在线程的角度看来就是寄存器的值可以任何时间任何地方突然“自主改变”。 而由用户执行的协程调度则不然。上...

点评 腾讯 的 协程库 libco

序 libco 是 腾讯开源的一个协程库。噱头很大,动不动就是承载了微信后台亿万并发。 敢说个不马上被喷成狗头。但是我偏就是要对这些光有名头没啥技术的东西祛魅。 上一片文章 里,点评了云风的 coroutine库,其中提到了 libco 犯了和云风一样的错。 其实 libco 的错误要比云风还要多的多。 废话不多说,接下来点评 libco libco 错在哪里 首先错误的,仓库上...

点评 云风 的 C库 coroutine

序 在知乎上看到两篇 吹嘘 云风的 coroutine 库的文章。 人啊就是这样的,出名了以后,就是垃圾也有人吹捧。 今天来点评下,云风的 coroutine 到底垃圾在哪里。又或者说,一个优秀的协程,应该优秀在哪里。 云风错在哪里 首先一个优秀的协程库,要做到“自然”。 什么是“自然”呢?就是要做到尽量不改变原来写同步阻塞IO逻辑的时候的代码。 因此引出第一错: 1 协程库...

基于 ucontext + iocp4linux 的超简协程库

虽然说,使用 异步最佳的实践是使用协程。 然而 c++20 的协程并不总是可用的。总不能说,不能更新编译器的地方就不配写代码吧。 因此,我在上一篇文章里说道,可以继续忍受回调地狱。或者使用有栈协程。 当然,如果使用 asio , 那么一切问题都不存在。asio 支持 有栈协程,无栈协程,daff‘s device 协程,还有最基础的,回调模式。 asio 简直就是个“宇宙级” 的异步库...

深入异步IO 第二篇: 正确使用 IOCP,正确设计 proactor

前言 干了那么多年码农,遇到 IO 从来都是写异步代码。从最初直面裸 epoll 写,到后来基本上依赖 asio 写。 最近研究 io_uring 后,试着用 io_uring 把 IOCP 那套 API 实现了。 以前呆在 asio 的舒适区,根本没关注过其他程序员对异步的理解。但是 windows 程序员是最多的,当我研究IOCP的时候, 以前被我忽略掉的那群写 IOCP 的程序员,...

深入理解异步IO

前言 干了那么多年码农,遇到 IO 从来都是写异步代码。从最初直面裸 epoll 写,到后来基本上依赖 asio 写。 最近研究 io_uring 后,试着用 io_uring 把 IOCP 那套 API 实现了。 以前呆在 asio 的舒适区,根本没关注过其他程序员对异步的理解。但是 windows 程序员是最多的,当我研究IOCP的时候, 以前被我忽略掉的那群写 IOCP 的程序员,...

批量提交IO提升性能

在基本完成 iocp4linux 后,我抽空在 rockpi 上测了下性能。 使用仓库里自带的例子 test/web_server/server.cpp,我测得了大约 6000req/s 的性能。 还不错。但是和 PC 上超过十万的性能相比,有那么点。。。弱鸡。 但是我通过 htop 注意到了一点。wrk 压测的时候, cpu1 是 cpu 100%。而且都是 红色的。说明cpu 都...

超轻量级 IOCP 协程库

在 上一篇 文章里,我提出了 iocp4linux 。 在编写 iocp4linux 的过程中,我需要写一些测试代码。 一开始,我随便的找了一个基于 IOCP 的 echo test 和一个简单的 web server。 首先确保这弄来的例子能在 windows 上编译通过。 然后修改 ifdef _WIN32守卫,在 linux 平台上改为使用 iocp.h 头文件。 然后很轻松的...

IOCP 移植到Linux上

序 windows 高性能IO使用的是 proactor 模型,而古代 Linux 上则是 reactor 模型。 因此跨平台的网络库,通常会选择实现为其中一种模型,然后在另一个平台上使用模拟。 比如 asio 使用 proactor 模型。Linux 上使用 epoll 模拟。 又比如 libevent 使用 reactor 模型, windows 上使用 iocp 模拟。 而将 i...

用iouring扩展asio

序 什么叫扩展asio? Beast给Asio增加了 HTTP 协议,不叫扩展asio。那什么叫扩展asio? 举个例子,给 asio 的 socket 对象,基于io_uring提供的 IORING_OP_SHUTDOWN 增加 async_shutdown() 接口,就算扩展asio。因为原本asio并没有异步shutdown功能。而且这个功能并不能靠组合原有的asio接口实现。这就叫...

重叠IO(proactor)是最理想的IO模型

reactor 和 proactor , 这种毫无联系的英文专用名词,很容易把人弄晕。 回归正途,使用精确的汉语描述,而非翻译,则正确的说法是: 多路复用IO 和 重叠 IO 模式。 所谓多路复用,顾名思义,就是好几个IO复用。。。 复用了谁?复用了线程。 它对比的是最传统的UNIX网络编程: 一个连接一个线程。并发就要开多线程。连接多了,线程就多,系统压力非常大。 而多路复用,则可以...

真正的重叠IO

不知有没有人想过,为何微软将windows 的异步API称为“重叠IO”而不是异步IO。 在我看来,重叠IO和异步IO的区别,主要在于发起IO后的动作。 重叠IO, 发起 IO 后,继续执行应用层的逻辑。应用可以选择在任何何时的地点再选择同步(阻塞等待 or 异步等待)IO的结果。 异步IO, 发起 IO 后,立即挂起当前业务逻辑(也就是立即非阻塞等待 IO 结果),回到事件循环,以便执...

不要 new 一个 char 数组当缓冲区

性能调优是一个有魔力的工作。最近研究到了 std::pmr::, 就想着看能否有些老代码能改进改进,提高下性能。 但是,测试的时候,发现还是有一些路径的效率不理想。 经过好久的排查,最终定位代码到这么一行 auto buffer_size = 5*1024*1024; auto buffer = std::make_unique<char[]>(buffer_size); ...