如何在 Linux 中访问新页面时减少延迟

How to reduce latency when access new page in linux

本文关键字:延迟 新页面 访问 Linux      更新时间:2023-10-16

Linux 中页面大小为 4KB,但我访问一个新页面,延迟大约是页面内部的两倍。如何减少此延迟?

这是我的测试代码。我使用 clock_gettime 来衡量 main 函数中的时间成本。

#define MEM_SIZE 4096 * 12
long long GetRT() {
    struct timespec tp;
    clock_gettime(CLOCK_REALTIME, &tp);
    return (long long) tp.tv_sec * 1000000000 + tp.tv_nsec;
}
void *InitSharedMemory() {
    int fd = shm_open("/test-steve", O_CREAT | O_RDWR, ACCESSPERMS);
    if (fd < 0) {
        perror("shm_open");
    }
    if (ftruncate(fd, MEM_SIZE) < 0) {
        perror("ftruncate");
    }
    void *mmap_ptr = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE,
                          MAP_SHARED | MAP_POPULATE, fd, 0);
    if (mmap_ptr == (caddr_t)-1) {
        perror("mmap");
    }
    return mmap_ptr;
}
int main()
{
    constexpr auto STEP = 512;
    char arr[STEP];
    for (int i = 0; i < STEP; ++i) {
        arr[i] = i;
    }
    int ret = 0;
    void *buffer = InitSharedMemory();
    for (int i = 0; i < 40; ++i) {
        if ((i % 0x8) == 0) {
            // *(char *) buffer = 'a';
        }
        auto t1 = GetRT();
        *(char *) buffer = 'a';
        auto t2 = GetRT();
        ret += t2 - t1;
        printf("cost: %lld nsn", t2 - t1);
        buffer  = (char *) buffer + STEP;
    }
    return ret;
}

结果如下,额外的延迟TLB丢失了吗?如何避免?

cost: 272 ns
cost: 73 ns
cost: 76 ns
cost: 74 ns
cost: 74 ns
cost: 75 ns
cost: 73 ns
cost: 76 ns
cost: 281 ns
cost: 74 ns
cost: 73 ns
cost: 76 ns
cost: 76 ns
cost: 74 ns
cost: 73 ns
cost: 76 ns
cost: 334 ns
cost: 76 ns
cost: 76 ns
cost: 76 ns
cost: 76 ns
cost: 73 ns
cost: 76 ns
cost: 76 ns
cost: 267 ns
cost: 74 ns
cost: 74 ns
cost: 75 ns
cost: 73 ns
cost: 76 ns
cost: 73 ns
cost: 76 ns
cost: 260 ns

恐怕您无法避免第一次点击页面的成本(如您的示例所示(。

当使用带有mmap()标志MAP_HUGETLB的大页面(2MB(时,可能会摊销此成本。

根据应用上下文,在分配后立即一次触摸每个页面的第一个字节(或任何字节(将强制提交(在 numa 硬件上可能很有用(。
这将产生很大的初始成本,但可能会导致后续访问的时间更可预测。