The Slow Code No Scanner Can Flag
A scanner flags performance anti-patterns — a nested loop, an N+1 query shape. It can't tell you your actual bottleneck, because the hotspot is a measured property of a running workload. That's a profiler's job, and BrassCoders says so.
A scanner flags performance anti-patterns — a nested loop, a string built in a loop, an N+1 query shape. It can’t tell you your actual bottleneck, because the hotspot is a measured property of a running workload, not a shape in the source. BrassCoders flags the patterns; finding where your program actually spends its time is a profiler’s job, and this is one more seam worth seeing clearly before you trust a scan to answer a question it can’t.
The slow code you’re imagining and the slow code that’s actually costing you are usually different lines, and only one of them has a shape a scanner can see.
What a Perf Scanner Flags
BrassCoders flags performance anti-patterns — structural shapes that are often slow: a loop nested inside a loop, += string building in a loop, a query issued once per row instead of once per batch. Those have a form, so a rule matches them, the same way on every run. AI assistants produce them regularly, and clearing them is real value.
An anti-pattern is a risk indicator, not a measurement. A doubly-nested loop is quadratic in theory and free in practice when it runs over five elements. The scanner flags the shape because the shape can be slow; whether it is slow on your data is a separate question the source doesn’t answer.
Why the Bottleneck Isn’t in the Pattern
BrassCoders reads static source, and a bottleneck is a runtime fact — it depends on how big the data is, how often the code runs, and how long it waits on I/O. The hotspot in a real program is frequently a line no anti-pattern rule would flag: a single database round-trip on a hot path, a JSON parse called a million times, a lock held a beat too long.
That’s the divergence that makes profiling non-optional. The flagged nested loop over a five-item list is noise; the unflagged requests.get inside a request handler is the entire latency budget. A scanner ranks by shape; production ranks by measured time. The two orderings routinely disagree, and only the second one is the one your users feel.
Where the Measurement Happens
The tools that find a real bottleneck measure a running program. py-spy samples a live Python process with almost no overhead and shows where wall-clock time goes. Scalene profiles CPU and memory together and attributes cost line by line. cProfile in the standard library records call counts and cumulative time. Each observes the program doing the work, which is the one thing a static scan can’t.
BrassCoders points to these in its performance-anti-patterns research rather than pretending to replace them. The scanner and the profiler answer different questions — “is this shape risky” versus “where does the time actually go” — and a workflow needs both answers.
How the Two Layers Fit
BrassCoders clears the structural anti-patterns statically so they don’t sit in the codebase masking the real hotspot, and the profiler measures where time actually goes under load. Run the scan and the accidentally-quadratic loops and in-loop string builds are flagged before they ship; run the profiler and you learn which line is actually costing you seconds.
Deterministic where a shape exists, measured where it doesn’t. The scanner never claims to have profiled your workload, because it never ran it — and a tool that reported a bottleneck it never measured would be guessing at the number that matters most.
pip install brasscoders
brasscoders --offline scan /path/to/your/project
The scan catches the anti-pattern with a shape. The bottleneck without one is the profiler’s job, and knowing which question you’re asking is half the speedup.
Frequently Asked Questions
Can static analysis find my performance bottleneck?
No. A scanner flags performance anti-patterns — code shaped in a way that's often slow, like a quadratic loop or string concatenation in a loop. It can't tell you where your program actually spends its time, because that depends on data sizes, call frequency, and I/O waits at runtime. The real bottleneck is a measured property of a running workload, and measuring it is a profiler's job.
What's the difference between a perf anti-pattern and a real bottleneck?
An anti-pattern is a structural shape a scanner can match — a nested loop, an N+1 query. A bottleneck is where your program actually spends time under real load. They diverge constantly: a flagged nested loop over five items costs nothing, while an unflagged single database call on a hot path dominates the runtime. Only measurement tells you which is which.
What actually finds performance bottlenecks?
A profiler that measures a running program: py-spy for low-overhead sampling, Scalene for combined CPU and memory profiling, cProfile in the standard library. They observe where time actually goes under a real workload, which is the one thing a static scan of source cannot do.
So what does BrassCoders do on performance?
BrassCoders flags the structural performance anti-patterns AI assistants ship — accidentally-quadratic loops, string building in a loop, N+1 query shapes — deterministically on every scan. Clearing those keeps them from masking the real hotspot, but finding where your program spends its time is the profiler's job, on the layer above the scan.