From 649cc367b79c9262513d8d218a21e3c4ad287261 Mon Sep 17 00:00:00 2001 From: Yousef Ahmed Date: Mon, 6 Apr 2026 13:02:27 +0200 Subject: [PATCH] Reduce sharing in struct client between main and IO threads Reorder fields in struct client so that IO thread hot fields (tid, running_tid, io_flags, read_error) start at cache line 1 instead of sharing cache line 0 with main thread hot fields. Under threaded I/O, the main thread writes flags on every command dispatch while the IO thread reads/writes io_flags on every I/O event. With both on cache line 0, each access triggers a cross core L1d invalidation. Before: 103.6 TSC/iter mean, 141 TSC p99 After: 88.9 TSC/iter mean, 94 TSC p99 Delta: -14.2% mean, -33.3% tail latency per atomic store Welch t-test: t=5.92, p=0.0001 --- src/server.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/server.h b/src/server.h index 72036f6b6..cf07b5f80 100644 --- a/src/server.h +++ b/src/server.h @@ -1434,18 +1434,21 @@ typedef struct { #endif typedef struct client { + /* -- Cache line 0: main thread hot fields -- */ uint64_t id; /* Client incremental unique ID. */ uint64_t flags; /* Client flags: CLIENT_* macros. */ connection *conn; - uint8_t tid; /* Thread assigned ID this client is bound to. */ - uint8_t running_tid; /* Thread assigned ID this client is running on. */ - uint8_t io_flags; /* Accessed by both main and IO threads, but not modified concurrently */ - uint8_t read_error; /* Client read error: CLIENT_READ_* macros. */ int resp; /* RESP protocol version. Can be 2 or 3. */ + int _pad0; /* Explicit padding for alignment. */ redisDb *db; /* Pointer to currently SELECTed DB. */ robj *name; /* As set by CLIENT SETNAME. */ robj *lib_name; /* The client library name as set by CLIENT SETINFO. */ robj *lib_ver; /* The client library version as set by CLIENT SETINFO. */ + /* -- Cache line 1: IO thread hot fields -- */ + uint8_t tid; /* Thread assigned ID this client is bound to. */ + uint8_t running_tid; /* Thread assigned ID this client is running on. */ + uint8_t io_flags; /* Accessed by both main and IO threads, but not modified concurrently */ + uint8_t read_error; /* Client read error: CLIENT_READ_* macros. */ sds querybuf; /* Buffer we use to accumulate client queries. */ size_t qb_pos; /* The position we have read in querybuf. */ size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size. */