The most striking finding from this analysis is the concentration of risk: three of the top five hotspots live in a single file, monotonic_align/core.c, and the remaining two are monolithic training loop functions in separate model directories. All five sit in the “debt” quadrant — zero commits in the last 30 days, untouched for 1,109 days — so the risk argument here is blast radius, not active regression. MockingBird has 1,051 analyzed functions, 155 of which score as critical; the five I focus on below represent the highest activity-weighted risk scores in the repository and collectively embody every major antipattern the analysis detected. I would start with train in models/synthesizer/train.py not because anyone is changing it right now, but because its cyclomatic complexity of 86 and fan-out of 83 mean the next person who touches it is walking into one of the most structurally perilous functions in the codebase.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
train | models/synthesizer/train.py | 17.3 | 86 | 6 | 83 |
_unellipsify | monotonic_align/core.c | 17.2 | 47 | 5 | 43 |
__pyx_memview_slice | monotonic_align/core.c | 17.2 | 54 | 5 | 37 |
__Pyx_ParseOptionalKeywords | monotonic_align/core.c | 16.1 | 33 | 5 | 15 |
train | models/vocoder/hifigan/train.py | 16.0 | 67 | 8 | 99 |
Large Repo Analysis
MockingBird is a large repository. To stay within memory constraints, this analysis used hybrid touch mode: structural complexity — CC, ND, FO — is measured precisely for every function. Git activity is tracked at the function level (via git log -L) only for files with 5 or more commits in the last 30 days; other files use a file-level approximation. Rankings therefore surface functions that are both structurally complex and in the most actively-changing parts of the codebase. Dormant code with high structural complexity will rank lower than it would under a full per-function analysis — to surface it, run hotspots analyze . --per-function-touches on a machine with sufficient memory.
Codemod / Tooling Files in Results
Three of the five top hotspots — _unellipsify, __pyx_memview_slice, and __Pyx_ParseOptionalKeywords — are functions inside monotonic_align/core.c. The source excerpts confirm this is Cython-generated C code: the __Pyx_ prefix, __Pyx_RefNannyDeclarations, __Pyx_INCREF/__Pyx_GOTREF macros, and the View.MemoryView comment annotations are all Cython runtime boilerplate. The high cyclomatic complexity and fan-out scores reflect the verbosity of Cython’s reference-counting and error-handling code generation, not maintainer decisions. To exclude this file from future analyses, add the following to .hotspotsrc.json: { "exclude": ["monotonic_align/core.c"] }. This will surface the real application-layer hotspots without generated code consuming three of the top five slots.
Repository triage at a glance
1,051 functions analyzed
The quadrant picture tells a clear story: 395 functions are structural debt and only 16 are in the “fire” quadrant — actively changing and complex. The top five hotspots are all debt. That doesn’t mean they’re safe; it means the risk is deferred, not resolved.
Calls an unusually large number of distinct functions (high fan-out), making it the structural centre of gravity for a subsystem.Complex Branching×6Complex Branching
High cyclomatic complexity — many independent execution paths, each a potential bug surface and required test case.Long Function×6Long Function
Function body is too long to review in a single pass; likely contains multiple distinct responsibilities.Exit Heavy×5Exit Heavy
Multiple return or throw paths dispersed through the body — each exit needs separate test coverage.Deeply Nested×5Deeply Nested
Control structures nested 4+ levels deep, making it hard to reason about the full execution state at inner branches.Stale Complex×5Stale Complex
High structural complexity but untouched for a long time — structural debt that will bite whoever opens it next.
God-function is the dominant pattern across the top hotspots. In Python, where duck typing means that a high fan-out count understates actual coupling — types are resolved at runtime, so each of those 83 or 99 callees could silently accept something unexpected — a god-function with broad fan-out is a particularly fragile artifact.
train — models/synthesizer/train.py
This is the top-ranked function in the repository, with an activity-weighted risk score of 17.28. The source excerpt makes clear why: train owns the entire Tacotron training lifecycle in a single function — directory scaffolding, device detection, GPU batch-size validation, model instantiation with a full hyperparameter spread, optimizer setup, and checkpoint loading. That’s before the training loop itself begins.
A cyclomatic complexity of 86 means there are 86 independent execution paths through this function. Every path is a potential bug surface and, in practice, a required test case. The nesting depth of 6 means some of those branches are six levels deep — the compatibility check for symbol-table shape differences is a visible example, where a loaded checkpoint triggers a cascade of conditional JSON config loading or dumping inside an already-nested GPU check. The fan-out of 83 distinct callees means a change anywhere in this function’s dependency graph can have unexpected side effects here, and vice versa.
This function has 0 commits in the last 30 days and hasn’t been touched in 1,109 days. There are no bug-linked commits or reverts on the file, so there’s no historical defect signal pushing urgency — but that dormancy is itself a risk factor. When training behavior next needs to change (a new schedule, a different checkpoint format, distributed training adjustments), the developer doing that work will need to reason through 86 paths and 83 callees simultaneously.
Recommendation: Extract the setup phase — directory creation, device selection, batch-size validation, and model instantiation — into named helper functions before anyone adds new training logic. Getting the cyclomatic complexity below 20 is achievable by pulling each logical phase into its own callable. The if weights_fpath.exists() compatibility block alone is a strong candidate for extraction.
_unellipsify — monotonic_align/core.c
Three of the five top hotspots live in monotonic_align/core.c. That concentration matters: whoever owns this file owns a significant share of the repository’s structural risk budget, even if no one has touched it in 1,109 days.
_unellipsify is a Cython-generated C function (see the vendor note below for why these score so highly). Its job, as the source makes clear, is to expand ellipsis indices in memory-view slice operations into full slice tuples — the Python equivalent of resolving arr[..., 0] into explicit per-dimension slices. The implementation iterates over index tuples, tracks ellipsis and slice presence with integer flags, and builds a result list through multiple branching paths. A cyclomatic complexity of 47 and nesting depth of 5 reflect the combinatorial logic of handling mixed index types across arbitrary dimensions, and the exit_heavy pattern flags the multiple early-return and error-exit paths throughout.
The fan-out of 43 is high for what is notionally a utility function, driven by the Cython runtime’s reference-counting macros (__Pyx_INCREF, __Pyx_GOTREF, error-handling jumps) that appear as distinct callees in static analysis.
Recommendation: This file should be excluded from routine refactoring targets — it is generated code (see vendor note). The actionable step is to add the exclusion pattern to .hotspotsrc.json so the generated C stops consuming attention in future analyses.
__pyx_memview_slice — monotonic_align/core.c
The second function from core.c in the top five, __pyx_memview_slice implements the low-level memory-view slicing operation that _unellipsify feeds into. The source shows it managing source and destination __Pyx_memviewslice structs, iterating over each dimension to compute start/stop/step values, and handling the distinction between a base memoryview and a _memoryviewslice sub-type — with an assertion on ndim > 0 guarding entry.
At CC 54, this is the most complex function in core.c among the top five. The deeply_nested and exit_heavy patterns confirm that the dimension-iteration logic branches heavily and exits through multiple error paths — each requiring its own reference-count cleanup, which the Cython runtime enforces. With 0 touches in 30 days and 1,109 days since last change, the blast-radius risk here is identical to _unellipsify: low near-term probability of being changed, but high consequence if it is.
Recommendation: Same as _unellipsify — exclude monotonic_align/core.c from the hotspot scan. The complexity here is an artifact of Cython’s code generation, not of maintainer decisions.
__Pyx_ParseOptionalKeywords — monotonic_align/core.c
The third core.c function in the top five handles keyword argument parsing for Cython-wrapped Python callables. The source shows it walking a kwds dictionary, matching each key against an array of known argument names, handling both Python 2 PyString and Python 3 PyUnicode paths through #if PY_MAJOR_VERSION < 3 preprocessor guards, and branching on duplicate-argument detection (goto arg_passed_twice) and unknown keyword types (goto invalid_keyword_type).
The cyclomatic complexity of 33 is moderate-to-high, but it is entirely a product of the dual-string-type compatibility logic and the argument-matching loop structure — both Cython boilerplate. The exit_heavy and deeply_nested patterns are consistent with a function that must handle multiple error conditions through goto-based cleanup paths, a C idiom that static analysis correctly reads as multiple independent exit paths.
Recommendation: Exclude alongside the rest of core.c. There is no maintainer action to take here.
train — models/vocoder/hifigan/train.py
This is the highest fan-out function in the top five — 99 distinct callees — and the deepest nesting depth at 8. The source excerpt shows why: it is the HiFi-GAN vocoder’s complete training entry point, initializing distributed process groups, creating three model components (Generator, MultiPeriodDiscriminator, MultiScaleDiscriminator) on the target CUDA device, loading or skipping checkpoints for both generator and discriminator optimizer states, wrapping models in DistributedDataParallel conditionally on GPU count, configuring two separate optimizers and two learning-rate schedulers, and then building the dataset and dataloader pipeline — all before the epoch loop starts.
A nesting depth of 8 means there are control structures eight levels deep in this function. In Python, that typically signals that rank-conditional logic, GPU-count branching, and checkpoint-existence checks are all nested inside one another rather than composed through helper functions. The god_function and long_function patterns are the direct consequence: this function knows too much about too many things.
At 0 touches in 30 days and 1,109 days since last change, this is structural debt. But with fan-out of 99 in Python — where duck typing means those 99 callees interact through runtime-resolved interfaces — the blast radius of any future modification is severe. A change to how distributed training is initialized, or to how checkpoint filenames are constructed, ripples through a function that has no seams at which to contain the change.
Recommendation: I would extract at minimum three named helpers before any new feature work touches this function: one for checkpoint discovery and loading, one for model and optimizer setup, and one for dataset and dataloader construction. That decomposition alone would bring the cyclomatic complexity below 25 and the fan-out below 40, and it would make each phase independently testable. The nesting depth of 8 should drop naturally as the conditional logic distributes across smaller functions.
What about the active changes in the repository?
While all five top hotspots are debt, the data also surfaces the most recently active code: functions in skills/speak/scripts/ — specifically render_timeline.py and noiz_tts.py — were each touched within the last day and sit in the “fire” quadrant. The main function in render_timeline.py (activity-weighted risk of 14.47, CC 33, 1 touch in 30 days) and synthesize in noiz_tts.py (activity-weighted risk of 13.36, CC 28, 1 touch in 30 days) are actively changing with meaningful structural complexity. They don’t break into the top five because their structural scores are lower than the training loops, but they carry live regression risk precisely because changes are landing in them right now. I’d put them on the watch list for the next sprint.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
god_function | 9 |
complex_branching | 6 |
long_function | 6 |
exit_heavy | 5 |
deeply_nested | 5 |
stale_complex | 5 |
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
Reproduce This Analysis
git clone https://github.com/babysor/MockingBird
cd MockingBird
git checkout 28dc5e14f12d7c754612af2fde8e78a4b03f8616
hotspots analyze . --mode snapshot --explain-patterns --force --hybrid-touches 5
To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.
I use Hotspots to highlight structural and activity risk — not “bad code.” I treat these findings as a prioritization aid, not a bug predictor. Editorial policy →