notes · · 3 min

Redis Under the Microscope: What 67 AST Tools Found Inside the In-Memory Engine

We benchmarked all 67 prod-code AST tools against redis/redis: 211,000 lines of C, event loop slicing down to epoll_wait, and static non-call guardrails.

On this page · 4 sections
  1. Slicing the Event Loop Dispatch Down to epoll_wait
  2. Client Error Replies and Driver Protocol Duplication
  3. Cross-Module Boolean Inversion and Non-Call Reference Guards
  4. Remote Pre-Flight Compilation in Memory Under clangd

redis/redis is the industry-standard in-memory data structure store, powering caching, real-time analytics, and low-latency message brokers across global infrastructure.

Written in C99, the codebase spans 211,529 lines across 219 core source files in src/ (with 76,566 declarations indexed monorepo-wide). Unlike high-level managed languages, C relies heavily on manual memory management, preprocessor macros, and multiplexed event loops. Refactoring C code requires deep semantic awareness to prevent pointer mismatches, broken macros, or invalid compilation units.

We evaluated all 67 prod-code AST tools against redis/redis (commit 7f0b7bfa01) hosted on remote 32-core LAN nodes with zero local laptop CPU consumption.


Slicing the Event Loop Dispatch Down to epoll_wait

Redis achieves single-threaded execution throughput via ae.c, an event loop multiplexer abstracting OS polling primitives (epoll, kqueue, evport, select).

We queried reciprocal-rank-fusion (RRF) search to isolate the primary event processing engine:

$ prod-code search "aeProcessEvents"
10 hit(s) for `aeProcessEvents` in 196 ms (76566 declarations, 844 files; ranked by words and typed graph and by meaning; 54656 of 76566 declarations embedded so far, the rest in the background)

 1. [function] aeProcessEvents  src/ae.c:500
    aeProcessEvents(eventLoop, AE_ALL_EVENTS|
    attribution [score 0.0328]: lexical: rank 1 (matched ae, process, event); dense: rank 1 (cosine 0.873)

 2. [function] aeProcessEvents  src/ae.h:108
    int aeProcessEvents(aeEventLoop *eventLoop, int flags);
    attribution [score 0.0323]: lexical: rank 2 (matched ae, process, event); dense: rank 2 (cosine 0.867)

 3. [function] aeProcessEvents  src/ae.c:365
    int aeProcessEvents(aeEventLoop *eventLoop, int flags)
    The function returns the number of events processed.
    attribution [score 0.0317]: lexical: rank 3 (matched ae, process, event); dense: rank 3 (cosine 0.852)

In 196 ms, dense semantic embeddings and lexical tokens matched aeProcessEvents at src/ae.c:365 with a cosine similarity of 0.852.

We executed backward AST program slicing on aeProcessEvents to trace downstream polling dependencies across C source modules:

$ prod-code slice src/ae.c --line 365 --depth 1
=== src/ae.c

[function] aeProcessEvents  src/ae.c:365-473 (the seed)
int aeProcessEvents(aeEventLoop *eventLoop, int flags)
{
    int processed = 0, numevents;
...
    if (eventLoop->maxfd != -1 ||
        ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
...
        numevents = aeApiPoll(eventLoop, tvp);
...
            if (!invert && fe->mask & mask & AE_READABLE) {
                fe->rfileProc(eventLoop,fd,fe->clientData,mask);
                fired++;
            }
...
    return processed;
}

=== src/ae.h

[class] aeEventLoop  src/ae.h:79-93 (depth 1, used by aeProcessEvents)
typedef struct aeEventLoop {
    int maxfd;
    int setsize;
    aeFileEvent *events;
    aeFiredEvent *fired;
...
} aeEventLoop;

=== src/ae_epoll.c

[function] aeApiPoll  src/ae_epoll.c:89-115 (depth 1, used by aeProcessEvents)
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
    aeApiState *state = eventLoop->apidata;
    int retval, numevents = 0;

    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,
            tvp ? (tvp->tv_sec*1000 + (tvp->tv_usec + 999)/1000) : -1);
...
    return numevents;
}

The AST slice traversed module boundaries, connecting the high-level event loop in src/ae.c directly to the aeEventLoop struct definition in src/ae.h and the underlying Linux epoll_wait syscall in src/ae_epoll.c:89.


Client Error Replies and Driver Protocol Duplication

Redis responds to client protocol violations and command errors using addReplyError. Tracking these points of egress reveals command validation density across database subsystems.

We ran structural AST search for addReplyError($$$) across all repository files:

$ prod-code structural-search 'addReplyError($$$)'
454 match(es) in 38 file(s) (845 scanned in 4538.88ms)

  • src/acl.c:1511:9  addReplyError(c, "-WRONGPASS invalid username-password pair or user is disabled.")
    └─ [$$$ = c, "-WRONGPASS invalid username-password pair or user is disabled."]
  • src/acl.c:3025:17  addReplyError(c,"The 'default' user cannot be removed")
    └─ [$$$ = c,"The 'default' user cannot be removed"]
  • src/aof.c:3304:9  addReplyError(c,"Background append only file rewriting already in progress")
    └─ [$$$ = c,"Background append only file rewriting already in progress"]
  • src/aof.c:3664:9  addReplyError(c, "A backup is already in progress, ABORT it first")
    └─ [$$$ = c, "A backup is already in progress, ABORT it first"]

In 4,538 ms, the tool identified 454 distinct error return branches across 38 files, extracting the client pointer and error payload without false positive substring matches.

AST clone detection surfaced structural duplication across bundled client drivers. In deps/hiredis/hiredis.c, Clone Group #382 matched 5 identical 12-line AST subtrees for reply object array validation:

$ prod-code duplicates --min-lines 12 --group 382
[Clone Group #382] 12 lines | 5 occurrences (Type-2 (Parameterized))
  • Occurrence 1: deps/hiredis/hiredis.c:190-201
  • Occurrence 2: deps/hiredis/hiredis.c:210-221
  • Occurrence 3: deps/hiredis/hiredis.c:247-258
  • Occurrence 4: deps/hiredis/hiredis.c:265-276
  • Occurrence 5: deps/hiredis/hiredis.c:285-296
  Preview:
    │     if (task->parent) {
    │         parent = task->parent->obj;
    │         assert(parent->type == REDIS_REPLY_ARRAY ||
    │                parent->type == REDIS_REPLY_MAP ||
    │                parent->type == REDIS_REPLY_SET ||
    │                parent->type == REDIS_REPLY_PUSH);

Surfacing structural clones allows library maintainers to consolidate duplicated parser validations into unified parser callbacks.


Cross-Module Boolean Inversion and Non-Call Reference Guards

Glob pattern matching in Redis is provided by stringmatch(pattern, string, nocase) in src/util.c. Inverting a utility predicate in C requires adjusting the function signature, inverting return expressions, updating declarations across header files, and rewriting call sites across subsystems.

We ran invert-boolean to invert stringmatch to stringmismatch:

$ prod-code invert-boolean --path src/util.c --to stringmismatch stringmatch
`stringmatch` → `stringmismatch` (src/util.c)

- the body returns the negation of what it returned
- 10 call(s) gain a `!`, 0 lose the `!` they had

26 changed line(s) in 4 file(s)

--- a/src/config.c
+++ b/src/config.c
@@ -1085,5 +1085,5 @@
             if (config->flags & HIDDEN_CONFIG) continue;
             if (dictFind(matches, config->name)) continue;
-            if (stringmatch(name, dictGetKey(de), 1)) {
+            if (!stringmismatch(name, dictGetKey(de), 1)) {
                 dictAdd(matches, dictGetKey(de), config);
             }

--- a/src/util.c
+++ b/src/util.c
@@ -243,6 +243,6 @@
 }
 
-int stringmatch(const char *pattern, const char *string, int nocase) {
-    return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
+int stringmismatch(const char *pattern, const char *string, int nocase) {
+    return !(stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase));
 }

--- a/src/util.h
+++ b/src/util.h
@@ -41,5 +41,5 @@
-int stringmatch(const char *p, const char *s, int nocase);
+int stringmismatch(const char *p, const char *s, int nocase);

not rewritten (1 reference(s) that are not a call — a function used as a value keeps its old meaning under its new name; nothing is written while any remains):
  src/debug.c:1080:45 `stringmatch` used as a value

the analyzer accepts the result: 0 errors
nothing was written; pass `apply: true` to make these edits

The transformation updated 26 lines across src/config.c, src/sentinel.c, src/util.c, and src/util.h. Crucially, the refactoring engine halted automated disk writes because of a non-call identifier reference in src/debug.c:1080:45 where stringmatch-test was referenced in a debug command table. This safety guardrail prevents silent breakage in reflection or command dispatch tables.


Remote Pre-Flight Compilation in Memory Under clangd

Modifying fundamental utilities in a compiled C codebase can trigger cascading compilation errors across hundreds of translation units. Rebuilding locally with make consumes battery, heats developer laptops, and risks leaving the repository tree in an unbuildable state.

prod-code validate verifies edits in an in-memory overlay using remote clangd language servers without altering on-disk files.

We validated src/util.c clean, followed by a simulated syntax error:

$ prod-code validate src/util.c --from src/util.c
src/util.c: 0 error(s), 0 warning(s)
  (4 diagnostic(s) the file already had before this edit are not counted)
[prod-code] analysed in 0.54s

$ prod-code validate src/util.c --from /tmp/broken_util.c
src/util.c: 3 error(s), 0 warning(s)
  (4 diagnostic(s) the file already had before this edit are not counted)
  error: Use of undeclared identifier 'invalid' [undeclared_var_use] (src/util.c:245:79)
  error: Expected identifier [expected_unqualified_id] (src/util.c:245:88)
  error: Use of undeclared identifier 'syntax' [undeclared_var_use] (src/util.c:245:91)
[prod-code] analysed in 0.52s

In 0.52 seconds, remote clangd analyzed the proposed translation unit in RAM, filtered pre-existing platform diagnostics, caught the undeclared identifiers, and ensured invalid C patches never touch physical storage.


In low-latency systems software written in C, refactoring engines cannot treat code as raw strings; maintaining correctness requires semantic control-flow slicing across compilation units and compiler-backed in-memory validation that prevents unverified edits from breaking production builds.

Cite this article
Citation
Alexander Panasenko (2026-09-30). Redis Under the Microscope: What 67 AST Tools Found Inside the In-Memory Engine. https://prod.codes/blog/redis-under-the-microscope-67-ast-tools/