agentleFS
peopleforresterpeopleforrester/claude-dotfiles/skills/quality/performance-reviewer/SKILL.md

performance-reviewer

Skill3 starsChanged 7 months agoMITView on GitHub

Performance analysis and optimization. Use when reviewing code for performance issues, identifying bottlenecks, or optimizing slow operations. Covers frontend, backend, and database performance.

Files
SKILL.md

Performance Reviewer

Identify and resolve performance issues.

When to Use

  • Reviewing code for performance
  • Investigating slow operations
  • Optimizing database queries
  • Improving frontend performance
  • Pre-launch performance audit

Common Performance Issues

N+1 Query Problem

Symptom: Many database queries in a loop

// Bad: N+1 queries
const users = await User.findAll();
for (const user of users) {
  user.orders = await Order.findByUserId(user.id); // N queries!
}

// Good: Eager loading
const users = await User.findAll({
  include: [{ model: Order }]
});

// Good: Batch loading
const users = await User.findAll();
const userIds = users.map(u => u.id);
const orders = await Order.findByUserIds(userIds);
const ordersByUser = groupBy(orders, 'userId');
users.forEach(u => u.orders = ordersByUser[u.id] || []);

Missing Indexes

Symptom: Slow queries on filtered columns

-- Check for missing indexes
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

-- Add index
CREATE INDEX idx_orders_user_id ON orders(user_id);

Unbounded Queries

Symptom: Loading entire tables

// Bad: No limit
const allUsers = await User.findAll();

// Good: Paginated
const users = await User.findAll({
  limit: 20,
  offset: page * 20
});

Synchronous Blocking

Symptom: Blocking event loop

// Bad: Blocking file read
const data = fs.readFileSync('large-file.json');

// Good: Async read
const data = await fs.promises.readFile('large-file.json');

// Good: Streaming for large files
const stream = fs.createReadStream('large-file.json');

Memory Leaks

Symptom: Growing memory usage

// Bad: Growing array
const cache = [];
app.get('/data', (req, res) => {
  cache.push(req.body); // Never cleared!
});

// Good: Bounded cache with eviction
const cache = new LRUCache({ max: 1000 });

Frontend Performance

Bundle Size

# Analyze bundle
npx vite-bundle-visualizer

# Check specific package size
npx bundlephobia lodash

Optimizations:

  • Tree-shake unused code
  • Code-split by route
  • Lazy load below-fold content
  • Use lighter alternatives
// Bad: Import entire library
import _ from 'lodash';

// Good: Import specific functions
import debounce from 'lodash/debounce';

Render Performance

// Bad: Re-renders on every parent render
function UserList({ users }) {
  return users.map(user => (
    <UserCard key={user.id} user={user} />
  ));
}

// Good: Memoize expensive components
const UserCard = React.memo(function UserCard({ user }) {
  return <div>{user.name}</div>;
});

// Good: Memoize expensive calculations
const sortedUsers = useMemo(
  () => users.sort((a, b) => a.name.localeCompare(b.name)),
  [users]
);

Image Optimization

// Bad: Unoptimized images
<img src="/large-photo.jpg" />

// Good: Optimized with Next.js
import Image from 'next/image';
<Image
  src="/photo.jpg"
  width={400}
  height={300}
  loading="lazy"
  placeholder="blur"
/>

Backend Performance

Caching

// Add caching layer
const cache = new Redis();

async function getUser(id: string) {
  // Check cache first
  const cached = await cache.get(`user:${id}`);
  if (cached) return JSON.parse(cached);

  // Fetch from database
  const user = await db.user.findUnique({ where: { id } });

  // Cache for 5 minutes
  await cache.setex(`user:${id}`, 300, JSON.stringify(user));

  return user;
}

Connection Pooling

// Good: Connection pool
const pool = new Pool({
  max: 20,          // Max connections
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

Async Operations

// Bad: Sequential
const user = await getUser(id);
const orders = await getOrders(id);
const reviews = await getReviews(id);

// Good: Parallel
const [user, orders, reviews] = await Promise.all([
  getUser(id),
  getOrders(id),
  getReviews(id)
]);

Database Performance

Query Optimization

-- Check query plan
EXPLAIN ANALYZE SELECT ...;

-- Common optimizations:
-- 1. Add appropriate indexes
-- 2. Select only needed columns
-- 3. Use LIMIT for pagination
-- 4. Avoid SELECT *
-- 5. Use JOINs instead of subqueries when appropriate

Index Strategy

Query PatternIndex Type
Equality (=)B-tree
Range (<, >, BETWEEN)B-tree
Text searchGIN/Full-text
JSON fieldsGIN
GeospatialGiST

Performance Metrics

Core Web Vitals

MetricTargetDescription
LCP< 2.5sLargest Contentful Paint
FID< 100msFirst Input Delay
CLS< 0.1Cumulative Layout Shift

Backend Metrics

MetricTargetDescription
P50 Latency< 100msMedian response time
P99 Latency< 500ms99th percentile
Error Rate< 0.1%Failed requests
ThroughputVariesRequests per second

Performance Review Checklist

Database

  • Queries use indexes effectively
  • No N+1 query patterns
  • Results are paginated
  • Connections are pooled
  • Slow query logging enabled

Backend

  • Heavy operations are async
  • Appropriate caching in place
  • No memory leaks
  • Parallel where possible
  • Timeouts configured

Frontend

  • Bundle size optimized
  • Images optimized and lazy-loaded
  • Code-splitting implemented
  • Expensive renders memoized
  • Core Web Vitals passing

Profiling Tools

Node.js

# CPU profiling
node --prof app.js
node --prof-process isolate-*.log > processed.txt

# Memory profiling
node --inspect app.js
# Open chrome://inspect

Frontend

// Performance timing
performance.mark('start');
// ... operation ...
performance.mark('end');
performance.measure('operation', 'start', 'end');
console.log(performance.getEntriesByName('operation'));

Database

-- PostgreSQL: Enable slow query log
ALTER SYSTEM SET log_min_duration_statement = 100;
SELECT pg_reload_conf();

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.