Repository: valkey-io/valkey
File: src/server.h (C/C++)

Code before:
typedef struct ClientModuleData {
    void *module_blocked_client;               /* Pointer to the ValkeyModuleBlockedClient associated with this
                                                * client. This is set in case of module authentication before the
                                                * unblocked client is reprocessed to handle reply callbacks. */
    void *module_auth_ctx;                     /* Ongoing / attempted module based auth callback's ctx.
                                                * This is only tracked within the context of the command attempting
                                                * authentication. If not NULL, it means module auth is in progress. */
    ValkeyModuleUserChangedFunc auth_callback; /* Module callback to execute
                                                * when the authenticated user
                                                * changes. */
    void *auth_callback_privdata;              /* Private data that is passed when the auth
                                                * changed callback is executed. Opaque for
                                                * the Server Core. */
    void *auth_module;                         /* The module that owns the callback, which is used
                                                * to disconnect the client if the module is
                                                * unloaded for cleanup. Opaque for the Server Core.*/
} ClientModuleData;

typedef struct client {
    /* Basic client information and connection. */
    uint64_t id; /* Client incremental unique ID. */
    connection *conn;
    /* Input buffer and command parsing fields */
    sds querybuf;         /* Buffer we use to accumulate client queries. */
    size_t qb_pos;        /* The position we have read in querybuf. */
    bool is_qb_full_read; /* True if the last read returned the maximum allowed bytes */
    robj **argv;          /* Arguments of current command. */
    int argc;             /* Num of arguments of current command. */
    int argv_len;         /* Size of argv array (may be more than argc) */
    size_t argv_len_sum;  /* Sum of lengths of objects in argv list. */
    int reqtype;          /* Request protocol type: PROTO_REQ_* */
    int multibulklen;     /* Number of multi bulk arguments left to read. */
    long bulklen;         /* Length of bulk argument in multi bulk request. */
    long long woff;       /* Last write global replication offset. */
    /* Command execution state and command information */
    struct serverCommand *cmd;           /* Current command. */
    struct serverCommand *lastcmd;       /* Last command executed. */
    struct serverCommand *realcmd;       /* The original command that was executed by the client */
    struct serverCommand *io_parsed_cmd; /* The command that was parsed by the IO thread. */
    time_t last_interaction;             /* Time of the last interaction, used for timeout */
    serverDb *db;                        /* Pointer to currently SELECTed DB. */
    /* Client state structs. */
    ClientPubSubData *pubsub_data;    /* Required for: pubsub commands and tracking. lazily initialized when first needed */
    ClientReplicationData *repl_data; /* Required for Replication operations. lazily initialized when first needed */
    ClientModuleData *module_data;    /* Required for Module operations. lazily initialized when first needed */
    multiState *mstate;               /* MULTI/EXEC state, lazily initialized when first needed */
    blockingState *bstate;            /* Blocking state, lazily initialized when first needed */
    /* Output buffer and reply handling */
    long duration;                       /* Current command duration. Used for measuring latency of blocking/non-blocking cmds */
    char *buf;                           /* Output buffer */
    size_t buf_usable_size;              /* Usable size of buffer. */

Review comment (suggestion):
This adds 4 bytes (or 8, if the other surrounding fields need 8 bytes alignment) to every client in primaries and replicas, but we only need it for one very specific client.

Some other ideas to save memory:

* Use a flag. I know we have very few unused flags left, but it's fine to use them. (When it's full, we can add another 32 or 64 bits for more flags.)
* Change the return type of `readToQueryBuf` from void to bool or an enum, to indicate if it was a full or a short read.

Code after:
    void *module_blocked_client;               /* Pointer to the ValkeyModuleBlockedClient associated with this
                                                * client. This is set in case of module authentication before the
                                                * unblocked client is reprocessed to handle reply callbacks. */
    void *module_auth_ctx;                     /* Ongoing / attempted module based auth callback's ctx.
                                                * This is only tracked within the context of the command attempting
                                                * authentication. If not NULL, it means module auth is in progress. */
    ValkeyModuleUserChangedFunc auth_callback; /* Module callback to execute
                                                * when the authenticated user
                                                * changes. */
    void *auth_callback_privdata;              /* Private data that is passed when the auth
                                                * changed callback is executed. Opaque for
                                                * the Server Core. */
    void *auth_module;                         /* The module that owns the callback, which is used
                                                * to disconnect the client if the module is
                                                * unloaded for cleanup. Opaque for the Server Core.*/
} ClientModuleData;

typedef struct client {
    /* Basic client information and connection. */
    uint64_t id; /* Client incremental unique ID. */
    connection *conn;
    /* Input buffer and command parsing fields */
    sds querybuf;        /* Buffer we use to accumulate client queries. */
    size_t qb_pos;       /* The position we have read in querybuf. */
    robj **argv;         /* Arguments of current command. */
    int argc;            /* Num of arguments of current command. */
    int argv_len;        /* Size of argv array (may be more than argc) */
    size_t argv_len_sum; /* Sum of lengths of objects in argv list. */
    int reqtype;         /* Request protocol type: PROTO_REQ_* */
    int multibulklen;    /* Number of multi bulk arguments left to read. */
    long bulklen;        /* Length of bulk argument in multi bulk request. */
    long long woff;      /* Last write global replication offset. */
    /* Command execution state and command information */
    struct serverCommand *cmd;           /* Current command. */
    struct serverCommand *lastcmd;       /* Last command executed. */
    struct serverCommand *realcmd;       /* The original command that was executed by the client */
    struct serverCommand *io_parsed_cmd; /* The command that was parsed by the IO thread. */
    time_t last_interaction;             /* Time of the last interaction, used for timeout */
    serverDb *db;                        /* Pointer to currently SELECTed DB. */
    /* Client state structs. */
    ClientPubSubData *pubsub_data;    /* Required for: pubsub commands and tracking. lazily initialized when first needed */
    ClientReplicationData *repl_data; /* Required for Replication operations. lazily initialized when first needed */
    ClientModuleData *module_data;    /* Required for Module operations. lazily initialized when first needed */
    multiState *mstate;               /* MULTI/EXEC state, lazily initialized when first needed */
    blockingState *bstate;            /* Blocking state, lazily initialized when first needed */
    /* Output buffer and reply handling */
    long duration;                       /* Current command duration. Used for measuring latency of blocking/non-blocking cmds */
    char *buf;                           /* Output buffer */
    size_t buf_usable_size;              /* Usable size of buffer. */
    list *reply;                         /* List of reply objects to send to the client. */
    listNode *io_last_reply_block;       /* Last client reply block when sent to IO thread */