LINUX.ORG.RU

_copy_to_iter в perf top

 io-uring,


0

2

Я переезжаю в нашем видеостриминговом сервере с erlang на rust и для того, чтобы нащупать границы возможного, прикупил 100-гигабитного железа в ближайшем мвидео.

Простой бенчмарк между двумя десктопными компами: тредриппер раздает по http, ryzen принимает

Бенчмарк примитивнейший: скачиваем файлики и выбрасываем их.

На принимающей стороне perf top показывает:

Samples: 6M of event 'cycles:P', 4000 Hz, Event count (approx.): 1322687736231 lost: 0/0 drop: 0/0
Overhead  Shared Object     Symbol
  29.47%  [kernel]          [k] _copy_to_iter
  16.25%  libc.so.6         [.] __memmove_avx512_unaligned_erms
   4.15%  [kernel]          [k] mlx5e_build_rx_skb
   3.52%  [kernel]          [k] clear_page_erms
   2.33%  [kernel]          [k] check_heap_object
   1.83%  [kernel]          [k] __check_object_size.part.0
   1.56%  [kernel]          [k] mlx5e_copy_skb_header
   1.36%  [kernel]          [k] __napi_alloc_skb
   1.15%  libc.so.6         [.] _int_malloc

Правильно ли я понимаю, что это индикация того, что весь процессор (нагрузка на все ядра под 85%) занимается перекопированием из ядра в программу, причем жрет на это под 35% всех ресурсов?

Т.е. переход на io_uring может помочь?

Очень похоже на это.
Копирование между ядром и юзерспейс очень дорогое.
Для борьбы с этим сделали ZeroCopy (для отправки данных через сокеты), mmap для сокета af_packet, а вот для чтения я что-то не припоминаю похожих механизмов.

Не уверен, что io_uring сильно поможет.

Я знаю только 1 способ уменьшения стоимости такого копирования - ядро должно копировать данные в область памяти которая доступна процессу через mmap.

Если читаемые данные не нужно обрабатывать, то их можно копировать в /dev/zero внутри ядра

ИИшница подсказывает

#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>

void fast_flush_tcp(int socket_fd) {
    int null_fd = open("/dev/null", O_WRONLY);
    if (null_fd < 0) return;

    // Splice transfers data cleanly between descriptors entirely within the kernel
    while (splice(socket_fd, NULL, null_fd, NULL, 65536, SPLICE_F_NONBLOCK) > 0) {
        // Kept looping until the source buffer is empty
    }

    close(null_fd);
}

vel ★★★★★
()
Ответ на: комментарий от max_lapshin

io_uring - это способ асинхронно вызвать syscall и получить результат.
IMHO Если syscall будет пересылать данные в userspace, то накладные расходы на копирование из ядра никуда не денутся.
Я бы попробовал следующее: в клиенте выделить память для чтение данных через mmap и читать данные в такой буфер.

ИИшница подсказывает, что еще нужно выполнить

#include <netinet/tcp.h>

struct tcp_zerocopy_receive zc = {0};
zc.address = (__u64)addr; // The memory address obtained from mmap
zc.length = map_size;     // Size of the mapping region

// This system call maps the physical pages and tracks how much was mapped
int res = getsockopt(sock_fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &zc, sizeof(zc));
madvise(addr, zc.length, MADV_DONTNEED);

vel ★★★★★
()

Т.е. переход на io_uring может помочь?

Нет, потому что он нужен не для уменьшения копирований, а для уменьшения context switch.

maxcom ★★★★★
()
Ответ на: комментарий от maxcom

sendfile, ksplice - всё это в обязательном режиме безусловно требует ktls, сегодня не бывает нешифрованного трафика.

Но я говорю про лайв и тем более речь шла про прием. Сейчас ставлю эксперимент: залить на сторадж с 38 дисками максимум, что они вывезут.

У каждого по 2 гигабита записи, т.е. 38*1.7 = 60 гигабит входа. Надо попыхтеть.

max_lapshin ★★★★★
() автор топика

занимается перекопированием из ядра в программу

а iov/srviov включено?

etwrq ★★★★★
()
Ответ на: комментарий от Enthusiast

И техническая, и кадровая.

Я задолбался писать велосипеды на эрланге и на выходе получается, что даже 20 гигабит вытянуть - это целое достижение.

max_lapshin ★★★★★
() автор топика
Ответ на: комментарий от maxcom

я же говорю: с диска это только если устраивать игрища с kernel tls, но мне и не это нужно

max_lapshin ★★★★★
() автор топика
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария