Bali, Indonesia
Insights

Redesain Storage Engine Source Control: Menembus Batas Socket Buffer Kernel dan Log I/O

October 14, 2026
0:00
Ketika infrastruktur pelatihan model dan pipeline continuous integration meluas ke puluhan ribu akselerator komputasi pada lanskap rekayasa modern 2026, sistem version control konvensional langsung runtuh di bawah beban 'thundering herd'. Beban kerja ini tidak sekadar membaca berkas teks; ribuan runner mencoba menarik (fetch) puluhan gigabyte commit tree, blob checkpoint, dan metadata referensi secara bersamaan. Pendekatan standar berbasis Git daemon tradisional yang bertumpu pada runtime cgit/packfile di atas filesystem POSIX standar memicu saturasi I/O disk yang brutal dan kegagalan alokasi buffer jaringan pada kernel. Untuk mengatasi hambatan tersebut, storage backend source control harus direkayasa ulang layaknya distributed log database engine performa tinggi. Namun, memisahkan metadata relasional ke dalam database dokumen dan blob ke object store baru menyelesaikan separuh masalah. Hambatan terbesar berpindah ke subsistem jaringan kernel Linux: bagaimana storage engine memompa chunk data biner terkompresi dari disk log ke antarmuka jaringan 400GbE tanpa overhead context switch dan degradasi TCP write buffer.
Dalam sistem version control berskala sangat besar, struktur penyimpanan internal beroperasi mirip Content-Addressable Storage (CAS) yang digabungkan dengan write-ahead metadata log engine. Ketika serbuan 5.000 worker melakukan eksekusi 'git fetch' paralel terhadap pembaruan commit yang sama, arsitektur tradisional mengalami dua anomali kritis:
  1. Random Read Amplification: Storage engine melakukan traversal graph commit yang tersebar pada ribuan potongan log kecil, menyebabkan seek penalty tinggi dan cache eviction agresif pada buffer pool database metadata.
  2. TCP Socket Buffer Bloat: Daemon aplikasi membaca potongan objek ke user-space buffer lalu menulisnya kembali ke socket via syscall 'write()'. Saat interface jaringan mengalami micro-burst congestion, buffer kirim socket ('SO_SNDBUF') lekas penuh. Kernel memblokir thread worker atau memaksa alokasi 'sk_buff' yang memicu memory pressure ('slub/slab exhaustion').
TEXT
+-------------------------------------------------------------+
|                   Aplikasi Storage Engine                   |
+-------------------------------------------------------------+
           | (1) Metadata Lookup                 | (3) Object Stream
           v                                     v
+-----------------------+              +----------------------+
| Append-Only Log Index |              | Block Storage Engine |
| (LSM Tree / RocksDB)  |              | (Pack / Blob Chunks) |
+-----------------------+              +----------------------+
                                                 |
             +-----------------------------------+ 
             | (Direct I/O via NVMe)
             v
+-------------------------------------------------------------+
|                     Linux Kernel VFS                        |
+-------------------------------------------------------------+
             |
             | ZERO-COPY PIPELINE: splice() / io_uring
             v
+-------------------------------------------------------------+
|               Network Subsystem (TCP Sockets)               |
|   [ sk_buff Queue ] -> [ qdisc / FQ ] -> [ NIC Ring TX ]    |
+-------------------------------------------------------------+
Proses transfer tradisional yang memindahkan data: Disk --> Kernel Page Cache --> User-Space Memory Buffer --> Kernel Socket Buffer --> NIC Ring Buffer mengonsumsi cycle CPU hingga 65% hanya untuk memory copying (copy overhead) dan context switching ('page faults' dan 'syscall latency'). Solusinya adalah mentransformasi pipeline pengiriman data menjadi jalur zero-copy total langsung dari storage engine database ke TCP socket buffer.
Ketika socket TCP dibuat, kernel mengalokasikan struktur kontrol transmisi yang diatur oleh parameter 'net.ipv4.tcp_wmem'. Struktur ini mencakup memory footprint aktual dari payload data ditambah overhead metadata kernel yang disimpan dalam 'struct sk_buff'. Jika memory write buffer socket melonjak tanpa kontrol, TCP Receive Window (RCVWND) dan Congestion Window (CWND) dapat mengalami ketidakseimbangan fatal. Ketika client mengalami penurunan penyerapan paket data (misalnya runner CI mengalami CPU throttle lokal), socket write buffer di sisi server server database akan tersumbat. Storage engine yang menggunakan thread pooling konvensional akan mendapati seluruh worker thread tertahan pada syscall 'write()' atau epoll wait starvation.
TEXT
+-------------------------------------------------------------------------+
|                        Struktur Memori sk_buff                          |
+-------------------------------------------------------------------------+
| struct sk_buff | struct skb_shared_info | Payload Data (Frag Array)     |
| (Overhead)     | (Paging Metadata)      | (Direct Memory/Page Pointers) |
+-------------------------------------------------------------------------+
|<--------- Alokasi SLAB Kernel -------->|<----- Transferred via DMA ---->|
Untuk menghindari amplifikasi alokasi SLAB untuk 'skb_shared_info', ukuran payload yang di-stream oleh database storage engine harus disejajarkan dengan ukuran Maximum Transmission Unit (MTU) jaringan serta segmentasi TCP (TSO/GSO). Jika payload dikirim dalam pecahan kecil non-aligned, overhead 'sk_buff' kernel bisa membengkak hingga memakan 40% dari total memori yang dialokasikan untuk transmisi jaringan.
Dalam membangun storage daemon untuk log commit dan packfile streaming, pemilihan interface kernel sangat menentukan batas throughput sistem:
Metode TransferMekanisme Data PathContext Switches / I/OMemory Copy OverheadResiliensi Backpressure
read() / write()Disk -> User Space -> Socket2 syscalls (4 switches)2x Copy (Disk->RAM, RAM->Sock)Rendah (Menghabiskan RAM aplikasi)
sendfile(2)Page Cache -> Socket TX Ring1 syscall (2 switches)0x (Hanya ring descriptor)Sedang (Terkunci pada descriptor file)
splice(2)Pipe Buffer -> Socket Buffer1 syscall (2 switches)0x (Kernel Pipe Pages)Tinggi (Buffer ukuran pipa terkendali)
io_uringAsynchronous Ring Submission0 syscall (pada mode SQPOLL)0x (Registered Direct Buffers)Maksimal (Fully Non-blocking Ring)
Implementasi 'io_uring' modern memungkinkan storage engine mendaftarkan file descriptor database blob dan socket jaringan ke dalam direct buffer pool. Operasi 'IORING_OP_SPLICE' atau 'IORING_OP_SEND_ZC' meniadakan overhead round-trip kernel sepenuhnya, mengalirkan byte delta langsung dari storage drive berbasis NVMe-oF ke network interface controller (NIC).
Untuk mencegah memory exhaustion pada storage engine server saat ribuan transfer concurrent berlangsung, konfigurasi sysctl jaringan dan buffer memori harus diatur secara presisi. Berikut adalah konfigurasi produksi yang diterapkan pada node database server source control:
INI
# /etc/sysctl.d/99-storage-network-engine.conf

# Tingkatkan batas total memori jaringan TCP (dihitung dalam unit pages 4096 bytes)
# Format: min pressure max
net.ipv4.tcp_mem = 4194304 8388608 16777216

# Tuning buffer baca TCP (rmem) dan tulis TCP (wmem)
# Format: min default max (16MB max buffer untuk koneksi latensi menengah-tinggi)
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216

# Matikan TCP slow start setelah idle agar throughput transmisi commit tetap stabil
net.ipv4.tcp_slow_start_after_idle = 0

# Wajib aktifkan TCP Window Scaling (RFC 1323)
net.ipv4.tcp_window_scaling = 1

# Gunakan BBRv3 sebagai algoritma congestion control untuk menjaga throughput 
# tanpa memicu bufferbloat di queue switch rack
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# Perluas antrean backlog socket untuk menangani lonjakan handshake serentak
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 100000

# Optimasi TCP Selective Acknowledgment
net.ipv4.tcp_sack = 1
net.ipv4.tcp_dsack = 1
Penggunaan 'fq' (Fair Queueing) sebagai qdisc adalah prasyarat mutlak ketika mengaktifkan BBR. FQ melakukan pacing pada level per-flow, memastikan bahwa pengiriman paket tidak menyembur secara eksplosif ('packet bursts') yang dapat membebani antrean switch dan memicu drop paket yang mengharuskan retransmisi TCP berat.
Pada arsitektur internal backend storage engine, alur pengiriman payload blob commit dari storage disk ke socket klien dieksekusi melalui syscall 'splice(2)' atau antarmuka C berbasis pipe channel kernel. Berikut adalah implementasi ringkas protokol handler streaming blob yang mengunci kernel buffers langsung ke socket descriptor:
C
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>

/* 
 * Mengalirkan chunk objek database langsung dari storage fd ke socket client 
 * tanpa menyalin byte data ke user-space buffer memory.
 */
ssize_t stream_blob_zero_copy(int storage_fd, off_t *offset, int client_socket_fd, size_t length) {
    int pipe_fds[2];
    ssize_t total_transferred = 0;
    
    // Buat kernel pipe internal sementara
    if (pipe2(pipe_fds, O_NONBLOCK) == -1) {
        return -1;
    }

    while (total_transferred < length) {
        size_t to_transfer = length - total_transferred;
        
        // Splice dari block file storage engine ke kernel pipe buffer
        ssize_t bytes_in = splice(storage_fd, offset, pipe_fds[1], NULL, 
                                  to_transfer, SPLICE_F_MOVE | SPLICE_F_MORE);
        if (bytes_in <= 0) {
            if (bytes_in == 0 || errno != EAGAIN) break;
            continue;
        }

        // Splice dari kernel pipe langsung ke TCP socket write buffer
        ssize_t bytes_out = splice(pipe_fds[0], NULL, client_socket_fd, NULL, 
                                   bytes_in, SPLICE_F_MOVE | SPLICE_F_MORE);
        if (bytes_out <= 0) {
            if (bytes_out == 0 || errno != EAGAIN) break;
            continue;
        }

        total_transferred += bytes_out;
    }

    close(pipe_fds[0]);
    close(pipe_fds[1]);
    return total_transferred;
}
Implementasi ini secara radikal memangkas latensi alokasi memori internal daemon engine. Data halaman file dari subsistem NVMe ditarik ke pipe buffer oleh kernel, kemudian descriptor halaman tersebut dipetakan langsung ke struktur transmisi 'sk_buff' TCP socket tanpa satu pun loop duplikasi memori di user-space.
Untuk memverifikasi apakah pipeline jaringan mengalami hambatan transmisi atau socket memori tersumbat di tingkat OS, engineer wajib menggunakan 'ss' dengan flag statistik internal serta probe kernel dinamis. Perintah berikut digunakan untuk menganalisis metrik koneksi TCP aktif secara real-time pada port database/storage stream (port