Free-Threading, Rust Extensions, and High-Performance Python
Introduction
Chapter 1: The Python Performance Problem
- What “Slow” Actually Means for Python
- The Two Axes of Performance: Throughput and Latency
- Why Single-Threaded Python Can No Longer Scale
- When “It Works in Python” Is Not Good Enough
- The Historical Promise and the Modern Reality
Chapter 2: Inside CPython - How Python Actually Runs
- The Python Virtual Machine: Bytecode and the Main Loop
- Object Model: Reference Counting and Memory Management
- The Cost of Python Objects: Allocation, Layout, and Overhead
- How Python Executes: From Source to Machine Code
- Where Time Actually Goes: Anatomy of a Python Operation
Chapter 3: The Global Interpreter Lock - Anatomy of a Contention
- How the GIL Works: Implementation and Mechanics
- Why the GIL Exists: Reference Counting and Thread Safety
- What the GIL Actually Prevents (and What It Does Not)
- Measuring GIL Contention: Symptoms and Diagnosis
- The GIL Through History: Design Decisions That Endured
Chapter 4: Threading in Python - What You Get and What You Lose
- How Python Threads Really Work Under the GIL
- I/O-Bound Workloads: Where Threading Shines
- CPU-Bound Workloads: Where Threading Fails
- The Illusion of Parallelism and Its Cost
- Thread Safety, Data Races, and Shared Mutable State
Chapter 5: Multiprocessing and Process-Based Parallelism
- The Multiprocessing Module: Architecture and Trade-offs
- Inter-Process Communication: Queues, Pipes, and Shared Memory
- Memory Overhead and Serialization Costs
- When Multiprocessing Is the Right Choice
- Limitations: Start Methods, Pickling, and Portability
Chapter 6: Asyncio - Cooperative Concurrency
- How asyncio Works: Event Loops, Coroutines, and Futures
- I/O-Bound Performance: asyncio vs Threading
- When async Fails: CPU-Bound Tasks and Blocking Calls
- Structured Concurrency and Error Handling
- Ecosystem: Frameworks, Libraries, and Integration
Chapter 7: Choosing Your Concurrency Model
- Workload Classification: CPU-Bound, I/O-Bound, Mixed
- Performance Characteristics: Comparative Analysis
- Complexity and Maintainability Trade-offs
- Hybrid Approaches: Combining Models
- Decision Framework for Real Projects
Chapter 8: PEP 703 - Removing the Global Interpreter Lock
- The Proposal: What PEP 703 Changes and Why
- Design Goals and Non-Goals
- Reference Counting Without the GIL: Lock-Free and Atomic Operations
- The Thread State Model: Per-Thread Interpreters
- Compatibility Guarantees: What Stays the Same
Chapter 9: Free-Threading Architecture and Implementation
- The No-GIL Build: Configuration and Compilation
- Fine-Grained Locking: Per-Object and Per-Resource Locks
- Atomic Reference Counting and Memory Ordering
- Heap and Arena Allocators Without Global Locks
- Interpreter State Isolation and Shared Data
Chapter 10: Running Free-Threading Python Today
- Installation: Building and Running No-GIL CPython
- Python 3.13+ and the Free-Threading Flag
- Checking If Your Environment Is Free-Threaded
- Current Performance Characteristics and Benchmarks
- Ecosystem Readiness: What Works and What Does Not
Chapter 11: Thread Safety in Free-Threading Python
- The Problem: Data Races in Pure Python
- Atomic Operations: When Python Guarantees Safety
- Compound Operations and Their Vulnerabilities
- Defensive Programming Patterns for Thread Safety
- Built-in Thread Safety Guarantees
Chapter 12: Migrating to Free-Threading Python
- Auditing Your Codebase for Thread Safety
- C Extensions: What Breaks and Why
- Testing Strategies for Free-Threading Migration
- Gradual Migration: Dual-Mode Development
- Case Studies: Real Migrating Projects
Chapter 13: Performance of Free-Threading Python
- When Free-Threading Helps: True Parallelism in Pure Python
- When It Hurts: Lock Contention and Overhead
- Scaling with Cores: Benchmarking Methodology and Results
- Comparison: Free-Threading vs Multiprocessing vs asyncio
- Realistic Expectations for Production Workloads
Chapter 14: Why Rust for Python Extensions
- The Problem with C Extensions: Safety, Complexity, Maintenance
- What Rust Brings: Memory Safety Without Garbage Collection
- Performance Comparison: Rust, C, Cython, Numba
- Developer Experience and Ecosystem Maturity
- When Rust Is Overkill (and When It Is Not)
Chapter 15: Getting Started with PyO3 and maturin
- Installation: Rust, Cargo, PyO3, maturin, and Dependencies
- Project Structure: A Python Extension in Rust
- Building Your First Extension: From Rust to pip Installable
- Calling Rust from Python: Functions, Types, and Modules
- Testing Rust Extensions: Rust Tests and Python Tests
Chapter 16: Python and Rust Interoperability
- Type Mapping: Python Types and Their Rust Equivalents
- Passing Complex Data: Lists, Dicts, Custom Objects
- The GIL in PyO3: Python, pyfunction, and gil_refs
- Error Handling Across the Boundary: Exceptions and Result
- Callbacks: Calling Python from Rust
Chapter 17: Releasing the GIL and Parallel Rust
- Understanding GIL Release in PyO3: allow_threads
- Thread Pools: rayon, crossbeam, and std::thread
- Parallel Algorithms in Rust Extensions
- Shared Memory and Concurrent Data Structures
- When to Release the GIL and When Not To
Chapter 18: Memory Management at the Boundary
- Ownership Semantics: Who Owns What
- Zero-Copy Data Transfer: Shared Buffers and Views
- Python Object Lifecycle in Rust: Borrowing and References
- Avoiding Memory Leaks and Use-After-Free
- Large Data Structures and Transfer Patterns
Chapter 19: Packaging and Distribution
- maturin Build System: Workflow and Configuration
- Wheel Formats: Built vs Source Wheels
- Cross-Compilation and Manylinux/Docker Builds
- CI/CD: Testing and Publishing Rust Extensions
- Versioning, ABI Stability, and Release Strategy
Chapter 20: NumPy and the Vectorization Model
- Why NumPy Is Fast: Contiguous Arrays and SIMD
- Writing Vectorized Code: Idiomatic Patterns
- Under the Hood: NumPy’s C Extensions and Buffers
- Performance Gotchas: Copying, Views, and Broadcasting
- Modern Alternatives: Numba-accelerated NumPy and More
Chapter 21: Cython - Compiling Python to C
- How Cython Works: Typed Python as C Extension Generator
- Static Typing: When and How to Annotate
- Calling C Libraries from Cython
- Performance Analysis: What Cython Speeds Up
- Cython vs Rust: Trade-offs and Coexistence
Chapter 22: Numba and JIT Compilation
- How Numba Works: LLVM Backend and Compilation Modes
- Decorators and Compilation Triggers
- GPU Acceleration with Numba CUDA
- Performance Characteristics and Limitations
- Numba vs Cython vs Rust: Choosing for Your Workload
Chapter 23: PyPy and Alternative Python Implementations
- How PyPy Works: Tracing JIT and Meta-Interpreter
- Performance Profile: When PyPy Helps and Hurts
- Compatibility Issues and C Extension Problems
- Other Implementations: GraalPython, MicroPython, Jython
- The Future: Will Alternative Implementations Survive Free-Threading?
Chapter 24: Advanced Optimization Techniques
- Zero-Copy Data Movement and Buffer Protocols
- Serialization Optimization: msgpack, pickle, Arrow
- Caching Strategies: Result, Memoization, and Beyond
- Memory Layout and Cache Friendliness
- Algorithmic Optimization Before Premature Optimization
Chapter 25: Profiling Python Performance
- CPU Profiling: cProfile, py-spy, and Visualizers
- Memory Profiling: tracemalloc, objgraph, Memory Profiler
- Flame Graphs and Call Graphs
- Profiling Multithreaded and Multiprocess Code
- Profiling Native Extensions and Rust Code
Chapter 26: Designing Reliable Benchmarks
- Common Pitfalls: Warm-up, JIT, Caching, and Noise
- Microbenchmarks vs Macrobenchmarks
- Statistical Rigor: Repetition, Outliers, and Confidence
- Comparing Implementations Fairly
- Benchmarking Tools: pytest-benchmark, Criterion-Style for Python
Chapter 27: Production Deployment of Performance-Critical Python
- Containerization: Docker, Native Extensions, and Build Context
- Binary Compatibility and Deployment Environments
- Monitoring Performance in Production
- CI/CD for Python with Native Dependencies
- Incident Response: Debugging Performance Regressions
Chapter 28: The Future of Python Performance
- Where Free-Threading Is Heading: Python 3.14 and Beyond
- The Rust-Backed Python Ecosystem: Maturing and Expanding
- Subinterpreters, Parallel Garbage Collection, and More
- Choosing Your Strategy for the Next Five Years
- What You Should Do Now