Skip to content

Cyclomatic complexity survey: codebase is healthy overall, with a few concentrated hot spots #54

Description

@thunderInfy

Summary

I ran a cyclomatic complexity analysis over the repository using lizard (covering the Rust, Python, Scala, and Java sources) and wanted to share the results, since they may be useful for prioritizing refactoring and for readers navigating the code.

Headline numbers:

  • 13,417 functions analyzed; average cyclomatic complexity (CCN) is 3.3 - well under the conventional threshold of 10.
  • 822 functions exceed CCN 10, but 371 of those are generated Thrift serialization code (read_from_in_protocol / write_to_out_protocol in thunder/schema/*.rs and similar). Excluding generated code, only 451 of 12,100 hand-written functions (~3.7%) are over the threshold.
  • The feed-serving path most readers come to this repo for is the cleanest part of the codebase: home-mixer averages CCN 2.0 and visibility-filtering averages 1.6, each with only a handful of functions over 10.

Per-component breakdown (hand-written code only, sorted by average CCN)

Component Functions Avg CCN Max CCN CCN > 10
bdsm 223 5.3 136 28
phoenix 3,180 4.0 115 227
grox 694 3.9 47 41
thunder 64 3.8 20 7
under-the-hood 91 3.5 43 9
phoenix-rankall 264 3.5 39 23
simclusters 908 2.8 21 20
abuse-enforcement-service 510 2.2 34 10
botmaker 2,815 2.0 93 50
home-mixer 1,723 2.0 32 24
visibility-filtering 949 1.6 16 3

All remaining components (vm-ranker, scarecrow, agatha, clip, media-model-proxy, candidate-pipeline, visibility-filtering-client, user-cred-v2, adult-content, pnsfwmedia) average under 3.2 with few or no functions over the threshold.

Most complex hand-written functions

CCN NLOC Function Location
136 566 prefetcher_loop bdsm/runtime/batch_prefetcher.py
115 682 compute_batch_inputs_rust_quick phoenix/crates/serving/xai-recsys-engine/src/python.rs
93 374 Serializer constructor botmaker/src/java/com/twitter/botmaker/compiler/Serializer.java
72 148 _decide_hard_enforcement bdsm/runtime/score_results_sink_focal.py
66 509 compute_loop phoenix/xrex/cutedsl/ranker_fa4/flash_bwd_sm100.py
65 219 apply_mask phoenix/xrex/cutedsl/ranker_fa4/mask.py
62 375 __call__ phoenix/xrex/cutedsl/ranker_fa4/flash_fwd_sm100.py
56 265 save_checkpoint phoenix/xrex/train/trainer_recsys.py
55 556 from_record_batch phoenix/xrex/data/recsys/recsys_batch.py
54 232 Compiler::createASTNodeTree botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java

Observations

  1. Complexity concentrates in ML infrastructure, not ranking logic. The largest hot spots are Phoenix's serving engine, its hand-tuned flash-attention kernels in phoenix/xrex/cutedsl/ranker_fa4/ (where heavy branching is largely inherent to GPU kernel programming), and training checkpoint handling. The scoring, filtering, and visibility logic that determines what users see is simple and readable.

  2. Two functions stand out as genuine refactoring candidates:

    • prefetcher_loop in bdsm/runtime/batch_prefetcher.py - a single 566-line loop at CCN 136.
    • compute_batch_inputs_rust_quick in phoenix/crates/serving/xai-recsys-engine/src/python.rs - 682 lines at CCN 115, plus a second overload at CCN 61 in the same file.

    Both mix several responsibilities in one body and would benefit from being split into smaller units; for a repo whose stated goal is transparency and readability, these are the files where a reader is most likely to get lost.

  3. Generated code dominates the raw warning count. If the project ever adds a complexity linter to CI, excluding */schema/* and other Thrift-generated sources would keep the signal useful.

Reproducing

pip install lizard
lizard -l rust -l python -l scala -l java --CCN 10 \
  -x "*/target/*" -x "*/node_modules/*" -x "*/.git/*"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions