15 Prompts for Code Performance Optimization

Introduction

Performance optimization is not about guessing—it's about measuring, analyzing, and iterating. Every millisecond saved in a critical code path can translate into lower cloud costs, better user retention, and higher conversion rates. According to a 2023 Google study, a 0.1-second delay in mobile search results reduces user engagement by 2.5%. Yet many developers still rely on intuition rather than data-driven profiling.

This article provides 15 carefully crafted prompts that you can use with AI assistants (like ChatGPT or Claude) to systematically identify bottlenecks, optimize algorithms, reduce memory usage, and improve overall code efficiency. Each prompt includes a specific task, the exact prompt text, and a real-world example result. Whether you are debugging a slow API endpoint or refactoring a legacy monolith, these prompts will save you hours of trial and error.


Basic Prompts

1. Identify Hotspots in a Function

Task: Find the slowest parts of a given function.

Prompt:

Analyze the following Python function and identify which lines or operations are likely performance bottlenecks. Provide explanations and suggest optimizations.

```python
def process_data(items):
    result = []
    for item in items:
        transformed = item.strip().lower()
        if transformed not in ['', 'null', 'none']:
            result.append(transformed.upper())
    return result
**Example Result:**
- The `not in` check creates a list each iteration. Convert to a set: `stop_words = {'', 'null', 'none'}`.
- `strip()` and `lower()` call string methods twice per item. Combine into a single transformation.
- List comprehension would be faster than manual `append`.

**Optimized version:**
```python
stop_words = {'', 'null', 'none'}
def process_data(items):
    return [item.strip().lower().upper() for item in items if item.strip().lower() not in stop_words]

2. Profile Execution Time Line by Line

Task: Get a line-by-line breakdown of execution time.

Prompt:

Write a Python script using the `line_profiler` library to profile the function `calculate_stats` below. Show the output and explain which lines are slowest.

```python
def calculate_stats(numbers):
    total = sum(numbers)
    avg = total / len(numbers)
    variance = sum((x - avg) ** 2 for x in numbers) / len(numbers)
    return avg, variance
**Example Result:**

Line # Hits Time Per Hit % Time Line Contents

 4         1        500.0    500.0     20.0      total = sum(numbers)
 5         1        200.0    200.0      8.0      avg = total / len(numbers)
 6         1       1800.0   1800.0     72.0      variance = sum((x - avg) ** 2 ...
The variance calculation takes 72% of the time. Use NumPy or a single-pass algorithm to speed it up.

---

### 3. Compare Two Code Versions

**Task:** Benchmark two implementations side by side.

**Prompt:**

Compare the performance of these two Python functions using the timeit module. Run each 1000 times with a random list of 10,000 integers and report average time.

Version A:
def double_list_a(lst):
result = []
for i in lst:
result.append(i * 2)
return result

Version B:
def double_list_b(lst):
return [i * 2 for i in lst]

**Example Result:**
Version A: 1.2 ms per loop
Version B: 0.8 ms per loop (33% faster)
List comprehension avoids function call overhead and list resize operations.

---

### 4. Detect Unnecessary Allocations

**Task:** Find memory allocations that slow down code.

**Prompt:**

Review this Python snippet and point out any unnecessary memory allocations. Suggest fixes.

def merge_dicts(d1, d2):
    merged = {}
    for k, v in d1.items():
        merged[k] = v
    for k, v in d2.items():
        merged[k] = v
    return merged
**Example Result:**
Unnecessary dictionary resizing. Use `{**d1, **d2}` (Python 3.5+) or `d1 | d2` (Python 3.9+).

---

### 5. Optimize Loop with Early Exit

**Task:** Add early exit conditions.

**Prompt:**

Add an early exit to this loop to improve performance when the target is found early.

def find_first_negative(numbers):
    for num in numbers:
        if num < 0:
            return num
    return None
**Example Result:**
Already has early exit. The prompt is a trick—sometimes the code is already optimal for that aspect.

---

## Advanced Prompts

### 6. Convert Recursive to Iterative

**Task:** Replace recursion with iteration to avoid stack overhead.

**Prompt:**

Convert this recursive Fibonacci function into an iterative version and compare performance for n=35.

def fib_rec(n):
    if n <= 1:
        return n
    return fib_rec(n-1) + fib_rec(n-2)
**Example Result:**
Recursive: 2.3 seconds (many repeated calculations)
Iterative: 0.0001 seconds (linear time)

```python
def fib_iter(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

7. Use Multiprocessing for CPU-Bound Tasks

Task: Parallelize a CPU-bound function.

Prompt:

Rewrite this function to use Python's `multiprocessing.Pool` to process chunks of data in parallel. Explain the expected speedup.

```python
import math
def compute_sqrt(numbers):
    return [math.sqrt(n) for n in numbers]
**Example Result:**
```python
from multiprocessing import Pool
def compute_sqrt_parallel(numbers, workers=4):
    with Pool(workers) as p:
        return list(p.map(math.sqrt, numbers))

For 1 million numbers on a 4-core machine, expect ~3.5x speedup (due to overhead).


8. Reduce Database Query Count (N+1 Problem)

Task: Detect and fix N+1 queries.

Prompt:

Identify the N+1 query problem in this Django code and fix it using `select_related` or `prefetch_related`.

```python
def get_author_books():
    authors = Author.objects.all()
    for author in authors:
        books = Book.objects.filter(author=author)
        print(author.name, len(books))
**Example Result:**
N+1: 1 query for authors + N queries for books.
Fix: `authors = Author.objects.prefetch_related('book_set').all()` → 2 queries total.

---

### 9. Cache Expensive Function Results

**Task:** Implement memoization.

**Prompt:**

Add caching to this expensive function using functools.lru_cache. Measure the performance improvement for repeated calls.

def expensive_calc(x):
    import time
    time.sleep(0.1)  # simulate heavy work
    return x * x
**Example Result:**
Before: 0.1s per call
After: 0.1s first call, ~0s subsequent calls with same argument.

```python
from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_calc(x):
    import time
    time.sleep(0.1)
    return x * x

10. Use Vectorized Operations Instead of Loops

Task: Replace Python loops with NumPy vectorization.

Prompt:

Convert this loop-based calculation to use NumPy vectorization and benchmark both for an array of 100,000 elements.

```python
def add_arrays(a, b):
    result = []
    for i in range(len(a)):
        result.append(a[i] + b[i])
    return result
**Example Result:**
Loop: 45 ms
NumPy: 0.3 ms (150x faster)

```python
import numpy as np
def add_arrays_np(a, b):
    return np.add(a, b)

Expert Prompts

11. Memory Profile with memory_profiler

Task: Find memory leaks and high usage.

Prompt:

Use `memory_profiler` to track memory usage of this function line by line. Identify where memory spikes occur.

```python
def load_large_file():
    with open('big_file.txt', 'r') as f:
        data = f.read()
    lines = data.split('\n')
    processed = [line.upper() for line in lines]
    return processed
**Example Result:**
`f.read()` loads entire file into memory. Use `f.readline()` or memory-mapped file for large files.

---

### 12. Detect Async Bottlenecks

**Task:** Find blocking calls in async code.

**Prompt:**

Identify blocking synchronous calls in this asyncio code that prevent concurrency. Suggest fixes.

import asyncio
import time

async def fetch_data():
    await asyncio.sleep(0.1)
    time.sleep(0.5)  # blocking!
    return 42
**Example Result:**
`time.sleep()` blocks the event loop. Replace with `await asyncio.sleep(0.5)`. Use `loop.run_in_executor()` for CPU-bound tasks.

---

### 13. Use `__slots__` to Reduce Memory Per Object

**Task:** Optimize class memory usage.

**Prompt:**

Apply __slots__ to this class to reduce memory overhead. Show memory savings for 1 million instances.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
**Example Result:**
Without `__slots__`: ~56 bytes per instance (due to `__dict__`)
With `__slots__`: ~40 bytes per instance (28% reduction)

```python
class Point:
    __slots__ = ('x', 'y')
    def __init__(self, x, y):
        self.x = x
        self.y = y

14. Profile with cProfile and Visualize

Task: Generate a call graph to find bottlenecks.

Prompt:

Run this code with `cProfile` and use `snakeviz` to visualize the results. Identify the most time-consuming function.

```python
import time
def main():
    total = 0
    for i in range(1000):
        total += heavy_work(i)

def heavy_work(x):
    return sum(range(x * 100))
**Example Result:**
`heavy_work` accounts for 98% of runtime. The `sum(range(...))` pattern is inefficient for large ranges. Use arithmetic series formula: `n*(n-1)//2`.

---

### 15. Inline Function Calls to Reduce Overhead

**Task:** Eliminate function call overhead in hot loops.

**Prompt:**

Inline the function call inside this loop to improve performance. Benchmark before and after.

def square(x):
    return x * x

def sum_squares(n):
    total = 0
    for i in range(n):
        total += square(i)
    return total
**Example Result:**
Before: 0.12 ms for n=1000
After (inline): `total += i * i` → 0.08 ms (33% faster)

---

### 16. Use Generators for Lazy Evaluation

**Task:** Convert list to generator to save memory.

**Prompt:**

Rewrite this function to return a generator instead of a list. Compare memory usage for 10 million items.

def get_squares(n):
    return [i*i for i in range(n)]
**Example Result:**
List: ~80 MB for 10 million integers
Generator: ~0 MB (yields one at a time)

```python
def get_squares_gen(n):
    for i in range(n):
        yield i*i

17. Optimize Regular Expressions

Task: Compile regex and use raw strings.

Prompt:

Improve the performance of this regex matching by precompiling and using raw strings.

```python
import re
def find_emails(text):
    return re.findall('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', text)
**Example Result:**
```python
EMAIL_REGEX = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
def find_emails(text):
    return EMAIL_REGEX.findall(text)

Precompilation speeds up repeated calls by ~50%.


Conclusion

Performance optimization is a skill that improves with systematic practice. The 15 prompts above cover the most common scenarios: from basic hotspot detection to advanced memory profiling and concurrency tuning. Start by profiling before optimizing—measure twice, cut once. Integrate these prompts into your daily workflow, and you will write faster, more efficient code.

As next steps, we recommend reading the official Python profiling documentation (docs.python.org/3/library/profile.html) and exploring tools like py-spy for production profiling. Happy optimizing!

← All posts

Comments