Skip to the content.

multifd

MultiFDMethods 的数据传输主要是压缩

rg "MultiFDMethods.*\{"
migration/multifd-nocomp.c
454:static const MultiFDMethods multifd_nocomp_ops = {

migration/multifd.c
153:static const MultiFDMethods *multifd_ops[MULTIFD_COMPRESSION__MAX] = {};

migration/multifd-zlib.c
280:static const MultiFDMethods multifd_zlib_ops = {

migration/multifd-qatzip.c
381:static MultiFDMethods multifd_qatzip_ops = {

migration/multifd-uadk.c
310:static const MultiFDMethods multifd_uadk_ops = {

migration/multifd-zstd.c
268:static const MultiFDMethods multifd_zstd_ops = {

migration/multifd-qpl.c
698:static const MultiFDMethods multifd_qpl_ops = {

multifd 总是和压缩绑定到一起,

commit 0222111a22b2 (“migration: Remove non-multifd compression”)

multifd_send_setup 中配置压缩方法,其实这个是合理的,既然可以有多个 CPU 来发送,那么就让这些 CPU 先压缩。

基本流程

初始化的基本流程:

采用 multifd 模式,并不是多个 thread 同时遍历 dirty bitmap ,还是 migration thread 遍历, 但是会有多个 thread 来发送。对接流程在

关键结构体

migration thread 发送流程

dirty page iteration 还是在 migration thread 中进行的:

找到了 dirty page 之后,将其传递给 multifd 机制:

source multifd thread

target multifd thread

例如 multifd + zstd 的时候,其结果为

在 multifd_zstd_recv 中:

static int multifd_zstd_recv(MultiFDRecvParams *p, Error **errp)
{

    // ...
    for (i = 0; i < p->normal_num; i++) {
        // p->block 是 RAMBlock
        // p->normal[i] 是内存地址,所以,这一段代码的作用就是让 zstd 解压的数据直接写入到 RAMBlock 中
        ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
        z->out.dst = p->host + p->normal[i];
        z->out.size = page_size;
        z->out.pos = 0;

队列深度等价为 1

每个 thread 是一个 depth 为 1 的队列。 每个 MultiFDSendParams 只有一个 pending_job 标志 + 一个 p->data 数据槽(multifd_send() 里直接 swap 指针,migration/multifd.c:400-408)。主线程给一个 thread 派完任务后,必须等该 thread 写完网络并 qatomic_store_release(&p->pending_job, false) 之后才能再次使用该 channel。

所以 channels_ready 这个 semaphore 的计数实际上就等于”当前空闲 channel 数”。N 个 channel 全忙时,semaphore 耗尽,主线程阻塞在那里,直到某个 thread 完成一轮发送回到循环顶部 post 一次。

但要补充一下:

  1. 卡住的是 multifd 这一层的派发者,而调用方(RAM 保存路径)本来就是攒满一批页(multifd_queue_page 按 channel 各自的 buffer 攒 batch)才调一次 multifd_send() 做一次指针 swap,派发本身是零拷贝的,所以”depth 1”的代价被 batching 摊薄了——每个 depth-1 slot 装的是一批页而不是一页。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。