Как уменьшить задержку при доступе к новой странице в Linux - PullRequest
1 голос
/ 09 июля 2019

Размер страницы составляет 4 КБ в Linux, но я открываю новую страницу, задержка примерно вдвое больше, чем внутри страницы.Как я могу уменьшить эту задержку?

Вот мой тестовый код.Я использую clock_gettime для измерения затрат времени в основной функции.

#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 ns\n", 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

1 Ответ

2 голосов
/ 09 июля 2019

Боюсь, что вы не можете избежать стоимости первого попадания на страницу (как показано на вашем примере).

Может быть, эта стоимость может быть амортизирована при использовании огромных страниц (2 МБ) с MAP_HUGETLB во флагах mmap().

В зависимости от аппликативного контекста, одноразовое прикосновение к первому байту (или любому) каждой страницы сразу после выделения приведет к принудительной фиксации (может быть полезно на оборудовании numa).
Это будет иметь большие начальные затраты, но может привести к более предсказуемым временным интервалам для последующих обращений.

...