python-performance — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited python-performance (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Any task involving Python runtime performance: identifying bottlenecks, reducing execution time, fixing memory leaks, optimizing async code, parallelizing workloads, or replacing slow Python loops with vectorized operations.
| Symptom | Tool | Command |
|---|---|---|
| "It's slow" (general) | cProfile + snakeviz | python -m cProfile -o prof.out script.py && snakeviz prof.out |
| "This function is slow" (line-level) | line_profiler | kernprof -l -v script.py (decorate with @profile) |
| "Memory keeps growing" | memory_profiler | python -m memory_profiler script.py (decorate with @profile) |
| "Memory leaks in long-running process" | tracemalloc | tracemalloc.start(); snapshot = tracemalloc.take_snapshot() |
| "I/O bound" | py-spy (sampling) | py-spy top --pid <PID> |
| "GIL contention" | py-spy | py-spy record --native -o profile.svg --pid <PID> |
#### Profiling Workflow
# Quick cProfile workflow
import cProfile
import pstats
profiler = cProfile.Profile()
profiler.enable()
# ... code under test ...
profiler.disable()
stats = pstats.Stats(profiler).sort_stats("cumulative")
stats.print_stats(20) # Top 20 by cumulative time#### Asyncio Optimization
asyncio.TaskGroup (Python 3.11+) over asyncio.gather for structured concurrency: async with asyncio.TaskGroup() as tg:
task1 = tg.create_task(fetch_user(user_id))
task2 = tg.create_task(fetch_orders(user_id))
# Both complete or both cancel on errorloop.run_in_executor: result = await loop.run_in_executor(None, blocking_io_function, arg)await in tight loops. Batch operations: # Bad: sequential awaits
for item in items:
await process(item)
# Good: concurrent with bounded concurrency
sem = asyncio.Semaphore(10)
async def bounded(item):
async with sem:
return await process(item)
results = await asyncio.gather(*(bounded(i) for i in items))asyncio.Queue for producer-consumer patterns instead of polling.async with asyncio.timeout(5.0).#### Multiprocessing
ProcessPoolExecutor for CPU-bound work (bypasses GIL): from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor(max_workers=os.cpu_count()) as pool:
results = list(pool.map(cpu_heavy_function, data_chunks))multiprocessing.shared_memory for large data to avoid serialization overhead: from multiprocessing import shared_memory
shm = shared_memory.SharedMemory(create=True, size=array.nbytes)
shared_array = np.ndarray(array.shape, dtype=array.dtype, buffer=shm.buf)Pool.map / Pool.imap_unordered over manual Process management.threading (not multiprocessing) for I/O-bound parallelism (GIL is released during I/O).#### NumPy Vectorization
# Bad: 100x slower
result = [x * 2 + 1 for x in data]
# Good: vectorized
result = data * 2 + 1 # Bad
filtered = [x for x in data if x > threshold]
# Good
filtered = data[data > threshold]np.where for conditional assignment, np.einsum for tensor operations.out= parameter or in-place operations.numba.jit(nopython=True).#### Generator Pipelines (Memory Efficiency)
def read_chunks(path, chunk_size=8192):
with open(path, "rb") as f:
while chunk := f.read(chunk_size):
yield chunk
def process_pipeline(path):
chunks = read_chunks(path)
decoded = (chunk.decode("utf-8") for chunk in chunks)
lines = (line for chunk in decoded for line in chunk.splitlines())
return (parse(line) for line in lines if line.strip())itertools (chain, islice, groupby) for composing lazy pipelines.chunksize parameter in read_csv for row-by-row processing.#### Memory Optimization
__slots__ on data classes with many instances: class Point:
__slots__ = ("x", "y", "z")
def __init__(self, x: float, y: float, z: float):
self.x, self.y, self.z = x, y, z
# Saves ~40% memory per instance vs regular classsys.getsizeof and pympler.asizeof to measure object memory.array.array over lists for homogeneous numeric data.weakref for caches that should not prevent garbage collection.sys.intern(string).#### C Extension Paths (When Python Is Not Fast Enough)
cdef types for 10-100x speedup.bottleneck AND vectorization/multiprocessing cannot solve it.
# Optimized from 4.2s to 0.3s by vectorizing the distance calculation.
# See: profiling results in docs/perf/distance-calc-2024-03.md@lru_cache on functions with large/unhashable arguments (memory leak).global interpreter lock assumptions (using threads for CPU-bound work).+= creates new string each time; use "".join(parts)).pandas for row-by-row iteration (iterrows is 100x slower than vectorized).Before marking a task done when this skill was active:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.