Zero-copy và sendfile

Zero-copy là kỹ thuật truyền dữ liệu giảm tối đa số lần sao chép dữ liệu giữa các vùng nhớ. sendfile là system call của hệ điều hành cho phép di chuyển dữ liệu trực tiếp giữa hai file descriptor ngay dưới tầng kernel, không phải nạp dữ liệu lên tầng ứng dụng qua RAM. Nhờ đó giảm đáng kể thời gian, số lần copy và chi phí context switch giữa user space và kernel space.

Vấn đề mà zero-copy giải quyết

Cách truyền file truyền thống (đọc file rồi ghi ra socket ở tầng ứng dụng) phải copy dữ liệu nhiều lần: từ disk vào page cache của kernel, từ kernel lên buffer của ứng dụng, từ buffer ứng dụng trở lại kernel buffer của socket, rồi mới ra network card. Mỗi lần copy tốn CPU và bộ nhớ. sendfile (có trên Unix hiện đại, Linux từ kernel 2.1) cho phép kernel gửi dữ liệu từ page cache thẳng tới socket, chỉ còn lần copy cuối tới buffer của network card.

Ứng dụng trong Kafka

Zero-copy là một trong những kỹ thuật cốt lõi giúp Kafka đạt throughput cao. Kafka dùng sendfile (qua FileChannel.transferTo của Java NIO) để gửi dữ liệu log từ disk thẳng ra socket cho consumer mà không nạp qua bộ nhớ ứng dụng JVM. Một lưu ý quan trọng: bật TLS sẽ vô hiệu hóa zero-copy, vì dữ liệu phải được mã hóa ở tầng ứng dụng nên không thể đi thẳng từ page cache ra socket.

Giới hạn trong ASGI

Core spec của ASGI gửi response body dưới dạng các message http.response.body chứa bytes ở tầng ứng dụng Python, nên không tận dụng được sendfile - dữ liệu file vẫn phải đi qua bộ nhớ Python. Đây là hạn chế khi phục vụ file tĩnh kích thước lớn.

ASGI bổ sung khả năng này qua hai extension tùy chọn: http.response.pathsend (ứng dụng gửi đường dẫn tuyệt đối của file, server tự sendfile, không trộn với http.response.body) và http.response.zerocopysend (ứng dụng truyền một file descriptor để server gọi os.sendfile, có thể trộn với body). Các extension này chỉ dùng được khi cả server (ví dụ Granian, Hypercorn) và ứng dụng cùng hỗ trợ.