Skip to content
Agentmart
Submit a tool

python-performance

Profile and optimize Python CPU, memory, I/O, concurrency, and numerical performance.

Skill by caarlos0

IndexedMIT★ 224
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/caarlos0-python-performance

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Profile and optimize Python CPU, memory, I/O, concurrency, and numerical performance.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/python-performance

What's inside

Skill name
python-performance
Description
Profile and optimize Python CPU, memory, I/O, concurrency, and numerical performance.
License
MIT
Instructions
133 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Python Performance

Name the metric first: wall time, CPU time, allocation count, retained heap,
peak RSS, or I/O wait. Pin Python, dependencies, input, and environment; then
change one profiled cause.

## Measurement

- Use `pyperf` for repeatable benchmarks with calibration, worker processes,
  metadata, and statistical comparison.
- Use `timeit` only for small fragments. It disables cyclic GC during timing
  unless explicitly re-enabled, which can make allocation-heavy code look
  unlike production.
- Use `cProfile` for call counts and cumulative development profiles; use a
  sampling profiler such as `py-spy` for lower-overhead process observation.
- Use `tracemalloc` for Python-managed allocations. If RSS grows while its
  traces remain stable, inspect native allocations or fragmentation with
  Memray or an OS profiler.
- `sys.getsizeof` is shallow; it does not measure referenced objects.
- Use `python -X importtime` before changing startup imports.

## Data structures and Python operations

Choose from access patterns:

| Need | Prefer |
|---|---|
| Membership or deduplication | `set` or `dict`, not repeated list scans |
| Queue operations at both ends | `collections.deque`, not `list.pop(0)` |
| Priority queue | `heapq` |
| Search in maintained sorted data | `bisect` |
| Mutable binary accumulation | `bytearray`, then `bytes(buffer)` |
| Many string fragments | collect fragments and `"".join(parts)` |

These choices change semantics and memory. Do not replace a list when callers
need indexing, slicing, or compact iteration.

Generators avoid eager materialization but add iteration overhead and cannot be
reused. Built-ins and comprehensions often move work into optimized C loops,
but they are not automatically faster for every workload.

`lru_cache` trades CPU for retained memory and invalidation. On an instance
method, cache keys retain `self`; avoid it when instances must be collected.
`@dataclass(slots=True)` or `__slots__` can reduce memory for many instances but
affects dynamic attributes, inheritance, weak references, serialization, and
framework integration.

## Memory and GC

CPython uses reference counting plus cyclic GC. Distinguish:

- growing Python allocation traces;
- retained reachable objects;
- native allocations;
- allocator fragmentation;
- peak RSS;
- allocation churn that increases CPU without retaining memory.

High RSS alone is not a leak. Tune GC thresholds, call `gc.freeze()`, or change
allocators only after pause, allocation, or copy-on-write measurements identify
the collector or allocator as the cause. GC defaults differ by Python version
and free-threaded build.

## Threads, asyncio, and processes

- Threads overlap many blocking I/O operations because those calls release the
  GIL. Pure-Python CPU threads do not execute bytecode in parallel under the
  normal GIL; native extensions may release it.
- `asyncio` is cooperative concurrency. Any blocking call or long CPU loop in a
  coroutine stalls the event loop. Use bounded queues when producers can outrun
  consumers, and preserve cancellation and shutdown.
- Processes provide CPU parallelism but add startup, pickling, IPC, memory, and
  failure handling. Include all of those in the benchmark.
- Start methods vary by platform and Python version. Libraries should not force
  a global method without owning application lifecycle.
- Free-threaded CPython enables parallel Python threads but adds evolving
  overhead, synchronization requirements, and extension compatibility. Test the
  exact interpreter and dependency set.

## I/O and services

- Use buffering for repeated small reads and writes. `readinto()` can reuse a
  buffer in measured binary pipelines but adds ownership complexity.
- Batch database and network operations to reduce round trips. Oversized
  batches increase memory, lock duration, tail latency, and retry scope.
- Avoid constructing expensive log messages when the level is disabled. Queue
  handlers move slow output off latency-sensitive threads but require bounded
  capacity, ordering, loss, and shutdown decisions.
- Preserve flush, EOF, error, retry, ordering, cancellation, and protocol
  behavior when optimizing I/O.

## NumPy and native acceleration

- Chained NumPy operations can allocate full-size temporaries. Use `out=`,
  in-place operations, chunking, or fused kernels only after CPU and memory
  profiles show the temporary matters.
- Check contiguity and strides when native kernels copy or traverse arrays
  poorly. Normalize layout once at a boundary, not repeatedly in a loop.
- BLAS, process pools, application threads, and runtimes can each create worker
  pools. Measure oversubscription before limiting them with `threadpoolctl` or
  environment settings.
- Warm Numba before benchmarking. It helps supported Python-loop work, not code
  already dominated by optimized NumPy kernels.
- Cython, PyO3/Rust, GPU code, and alternative runtimes add compilation,
  transfer, ABI, packaging, debugging, and maintenance. Batch enough work per
  boundary crossing to justify them and keep a tested Python path when useful.

## CPython specialization

Use `dis.dis(fn, adaptive=True)` after warm-up as supporting evidence for a hot
loop. Do not redesign APIs to preserve one specialized opcode; specialization
rules change between versions. Re-measure after Python upgrades.

## Regression guards

Use narrow allocation, output-size, startup, or memory guards when the
toolchain and platform are pinned. Wall-time gates require dedicated hardware
or enough margin to avoid flaking; keep shared-runner timing advisory. Never
compare runs with different GC modes, profilers, hooks, or calibration.

From caarlos0/dotfiles, MIT.

More from caarlos0/dotfiles

Signals

Stars
224
Forks
12
Open issues
0
Last commit (this folder)
Oct 20, 2026 (8 days ago)
Last release
Oct 1, 2026 (27 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from caarlos0

Cite this page

python-performance skill. Agent Mart. https://agentmart.dev/skills/caarlos0-python-performance (last updated 2026-10-24)