Improve perf for worker
This commit is contained in:
693
.cursor/commands/optimize-current-code.md
Normal file
693
.cursor/commands/optimize-current-code.md
Normal file
@@ -0,0 +1,693 @@
|
||||
# optimize-current-code
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this command when you want to:
|
||||
- Optimize performance of existing C# backend code
|
||||
- Optimize React/TypeScript frontend code
|
||||
- Improve code quality and maintainability
|
||||
- Reduce technical debt
|
||||
- Apply best practices to existing code
|
||||
- Optimize database queries and API calls
|
||||
- Improve bundle size and loading performance (frontend)
|
||||
- Enhance memory usage and efficiency (backend)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**For C# Backend:**
|
||||
- .NET SDK installed (`dotnet --version`)
|
||||
- Solution builds successfully
|
||||
- Understanding of current code functionality
|
||||
|
||||
**For React Frontend:**
|
||||
- Node.js and npm installed
|
||||
- Dependencies installed (`npm install`)
|
||||
- Application runs without errors
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Identify Code Type and Scope
|
||||
|
||||
Determine what type of code needs optimization:
|
||||
|
||||
**Ask user to confirm:**
|
||||
- Is this C# backend code or React frontend code?
|
||||
- What specific file(s) or component(s) need optimization?
|
||||
- Are there specific performance issues or goals?
|
||||
|
||||
**If not specified:**
|
||||
- Analyze current file in editor
|
||||
- Determine language/framework from file extension
|
||||
- Proceed with appropriate optimization strategy
|
||||
|
||||
### Step 2: Analyze Current Code
|
||||
|
||||
**For C# Backend (.cs files):**
|
||||
|
||||
Read and analyze the code for:
|
||||
|
||||
1. **LINQ Query Optimization**
|
||||
- N+1 query problems
|
||||
- Inefficient `ToList()` calls
|
||||
- Missing `AsNoTracking()` for read-only queries
|
||||
- Complex queries that could be simplified
|
||||
|
||||
2. **Async/Await Patterns**
|
||||
- Missing `async/await` for I/O operations
|
||||
- Blocking calls that should be async
|
||||
- Unnecessary `async` keywords
|
||||
|
||||
3. **Memory Management**
|
||||
- Large object allocations
|
||||
- String concatenation in loops
|
||||
- Unnecessary object creation
|
||||
- Missing `using` statements for disposables
|
||||
|
||||
4. **Code Structure**
|
||||
- Duplicate code
|
||||
- Long methods (>50 lines)
|
||||
- Complex conditional logic
|
||||
- Missing abstractions
|
||||
- Business logic in controllers
|
||||
|
||||
5. **Database Operations**
|
||||
- Inefficient queries
|
||||
- Missing indexes (suggest)
|
||||
- Unnecessary data loading
|
||||
- Transaction management
|
||||
|
||||
**For React Frontend (.tsx/.ts files):**
|
||||
|
||||
Read and analyze the code for:
|
||||
|
||||
1. **Component Performance**
|
||||
- Unnecessary re-renders
|
||||
- Missing `React.memo()` for pure components
|
||||
- Missing `useMemo()` for expensive calculations
|
||||
- Missing `useCallback()` for callback props
|
||||
- Large components (>300 lines)
|
||||
|
||||
2. **Data Fetching**
|
||||
- Using `useEffect()` instead of TanStack Query
|
||||
- Missing loading states
|
||||
- Missing error boundaries
|
||||
- No data caching strategy
|
||||
- Redundant API calls
|
||||
|
||||
3. **Bundle Size**
|
||||
- Large dependencies
|
||||
- Missing code splitting
|
||||
- Missing lazy loading
|
||||
- Unused imports
|
||||
|
||||
4. **Code Structure**
|
||||
- Duplicate components
|
||||
- Complex component logic
|
||||
- Missing custom hooks
|
||||
- Props drilling
|
||||
- Inline styles/functions
|
||||
|
||||
5. **Type Safety**
|
||||
- Missing TypeScript types
|
||||
- `any` types usage
|
||||
- Missing interface definitions
|
||||
|
||||
### Step 3: Create Optimization Plan
|
||||
|
||||
Based on analysis, create prioritized optimization plan:
|
||||
|
||||
**Priority 1 (Critical - Performance Impact):**
|
||||
- N+1 queries
|
||||
- Memory leaks
|
||||
- Blocking I/O operations
|
||||
- Unnecessary re-renders
|
||||
- Large bundle size issues
|
||||
|
||||
**Priority 2 (High - Code Quality):**
|
||||
- Missing async/await
|
||||
- Duplicate code
|
||||
- Business logic in wrong layers
|
||||
- Missing error handling
|
||||
- Poor type safety
|
||||
|
||||
**Priority 3 (Medium - Maintainability):**
|
||||
- Long methods/components
|
||||
- Complex conditionals
|
||||
- Missing abstractions
|
||||
- Code organization
|
||||
|
||||
**Present plan to user:**
|
||||
- Show identified issues
|
||||
- Explain priority and impact
|
||||
- Ask for confirmation to proceed
|
||||
|
||||
### Step 4: Apply C# Backend Optimizations
|
||||
|
||||
**Optimization 1: Fix N+1 Query Problems**
|
||||
|
||||
**Before:**
|
||||
```csharp
|
||||
var orders = await context.Orders.ToListAsync();
|
||||
foreach (var order in orders)
|
||||
{
|
||||
order.Customer = await context.Customers.FindAsync(order.CustomerId);
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```csharp
|
||||
var orders = await context.Orders
|
||||
.Include(o => o.Customer)
|
||||
.ToListAsync();
|
||||
```
|
||||
|
||||
**Optimization 2: Add AsNoTracking for Read-Only Queries**
|
||||
|
||||
**Before:**
|
||||
```csharp
|
||||
public async Task<List<Product>> GetProductsAsync()
|
||||
{
|
||||
return await context.Products.ToListAsync();
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```csharp
|
||||
public async Task<List<Product>> GetProductsAsync()
|
||||
{
|
||||
return await context.Products
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 3: Move Business Logic from Controllers**
|
||||
|
||||
**Before (Controller):**
|
||||
```csharp
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateOrder(OrderDto dto)
|
||||
{
|
||||
var order = new Order { /* mapping logic */ };
|
||||
var total = 0m;
|
||||
foreach (var item in dto.Items)
|
||||
{
|
||||
total += item.Price * item.Quantity;
|
||||
}
|
||||
order.Total = total;
|
||||
await context.Orders.AddAsync(order);
|
||||
await context.SaveChangesAsync();
|
||||
return Ok(order);
|
||||
}
|
||||
```
|
||||
|
||||
**After (Controller):**
|
||||
```csharp
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateOrder(CreateOrderCommand command)
|
||||
{
|
||||
var result = await mediator.Send(command);
|
||||
return Ok(result);
|
||||
}
|
||||
```
|
||||
|
||||
**After (Service/Handler):**
|
||||
```csharp
|
||||
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, OrderResult>
|
||||
{
|
||||
public async Task<OrderResult> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var order = request.ToEntity();
|
||||
order.CalculateTotal(); // Business logic in domain
|
||||
await repository.AddAsync(order, cancellationToken);
|
||||
return order.ToResult();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 4: Optimize String Operations**
|
||||
|
||||
**Before:**
|
||||
```csharp
|
||||
string result = "";
|
||||
foreach (var item in items)
|
||||
{
|
||||
result += item.Name + ", ";
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```csharp
|
||||
var result = string.Join(", ", items.Select(i => i.Name));
|
||||
```
|
||||
|
||||
**Optimization 5: Improve LINQ Efficiency**
|
||||
|
||||
**Before:**
|
||||
```csharp
|
||||
var results = await context.Orders
|
||||
.ToListAsync();
|
||||
results = results.Where(o => o.Total > 100).ToList();
|
||||
```
|
||||
|
||||
**After:**
|
||||
```csharp
|
||||
var results = await context.Orders
|
||||
.Where(o => o.Total > 100)
|
||||
.ToListAsync();
|
||||
```
|
||||
|
||||
**Optimization 6: Add Caching for Expensive Operations**
|
||||
|
||||
**Before:**
|
||||
```csharp
|
||||
public async Task<List<Category>> GetCategoriesAsync()
|
||||
{
|
||||
return await context.Categories.ToListAsync();
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```csharp
|
||||
public async Task<List<Category>> GetCategoriesAsync()
|
||||
{
|
||||
var cacheKey = "all-categories";
|
||||
if (cache.TryGetValue(cacheKey, out List<Category> categories))
|
||||
{
|
||||
return categories;
|
||||
}
|
||||
|
||||
categories = await context.Categories
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
|
||||
cache.Set(cacheKey, categories, TimeSpan.FromMinutes(10));
|
||||
return categories;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Apply React Frontend Optimizations
|
||||
|
||||
**Optimization 1: Replace useEffect with TanStack Query**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function ProductList() {
|
||||
const [products, setProducts] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/products')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
setProducts(data);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) return <div>Loading...</div>;
|
||||
return <div>{products.map(p => <ProductCard key={p.id} {...p} />)}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
function ProductList() {
|
||||
const { data: products, isLoading } = useQuery({
|
||||
queryKey: ['products'],
|
||||
queryFn: () => productsService.getAll()
|
||||
});
|
||||
|
||||
if (isLoading) return <div>Loading...</div>;
|
||||
return <div>{products?.map(p => <ProductCard key={p.id} {...p} />)}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 2: Memoize Expensive Calculations**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function OrderSummary({ items }: { items: OrderItem[] }) {
|
||||
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
||||
const tax = total * 0.1;
|
||||
const grandTotal = total + tax;
|
||||
|
||||
return <div>Total: ${grandTotal}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
function OrderSummary({ items }: { items: OrderItem[] }) {
|
||||
const { total, tax, grandTotal } = useMemo(() => {
|
||||
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
||||
const tax = total * 0.1;
|
||||
return { total, tax, grandTotal: total + tax };
|
||||
}, [items]);
|
||||
|
||||
return <div>Total: ${grandTotal}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 3: Memoize Components**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function ProductCard({ name, price, onAdd }: ProductCardProps) {
|
||||
return (
|
||||
<div className="card">
|
||||
<h3>{name}</h3>
|
||||
<p>${price}</p>
|
||||
<button onClick={() => onAdd()}>Add</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
const ProductCard = React.memo(function ProductCard({ name, price, onAdd }: ProductCardProps) {
|
||||
return (
|
||||
<div className="card">
|
||||
<h3>{name}</h3>
|
||||
<p>${price}</p>
|
||||
<button onClick={() => onAdd()}>Add</button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
**Optimization 4: Use useCallback for Callbacks**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function ProductList() {
|
||||
const [cart, setCart] = useState([]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{products.map(p => (
|
||||
<ProductCard
|
||||
key={p.id}
|
||||
{...p}
|
||||
onAdd={() => setCart([...cart, p])}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
function ProductList() {
|
||||
const [cart, setCart] = useState([]);
|
||||
|
||||
const handleAdd = useCallback((product: Product) => {
|
||||
setCart(prev => [...prev, product]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{products.map(p => (
|
||||
<ProductCard
|
||||
key={p.id}
|
||||
{...p}
|
||||
onAdd={() => handleAdd(p)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 5: Extract Custom Hooks**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function ProductList() {
|
||||
const [products, setProducts] = useState([]);
|
||||
const [filtered, setFiltered] = useState([]);
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const results = products.filter(p =>
|
||||
p.name.toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
setFiltered(results);
|
||||
}, [products, search]);
|
||||
|
||||
// render logic
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
function useProductFilter(products: Product[], search: string) {
|
||||
return useMemo(() =>
|
||||
products.filter(p =>
|
||||
p.name.toLowerCase().includes(search.toLowerCase())
|
||||
),
|
||||
[products, search]
|
||||
);
|
||||
}
|
||||
|
||||
function ProductList() {
|
||||
const [search, setSearch] = useState('');
|
||||
const { data: products } = useQuery(['products'], getProducts);
|
||||
const filtered = useProductFilter(products ?? [], search);
|
||||
|
||||
// render logic
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 6: Implement Code Splitting**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
import { HeavyComponent } from './HeavyComponent';
|
||||
|
||||
function App() {
|
||||
return <HeavyComponent />;
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
import { lazy, Suspense } from 'react';
|
||||
|
||||
const HeavyComponent = lazy(() => import('./HeavyComponent'));
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<HeavyComponent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization 7: Fix Type Safety**
|
||||
|
||||
**Before:**
|
||||
```typescript
|
||||
function processData(data: any) {
|
||||
return data.map((item: any) => item.value);
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
interface DataItem {
|
||||
id: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function processData(data: DataItem[]): number[] {
|
||||
return data.map(item => item.value);
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: Verify Optimizations
|
||||
|
||||
**For C# Backend:**
|
||||
|
||||
1. **Build solution:**
|
||||
```bash
|
||||
dotnet build src/Managing.sln
|
||||
```
|
||||
- Ensure no compilation errors
|
||||
- Check for new warnings
|
||||
|
||||
2. **Run tests (if available):**
|
||||
```bash
|
||||
dotnet test src/Managing.sln
|
||||
```
|
||||
- Verify all tests pass
|
||||
- Check for performance improvements
|
||||
|
||||
3. **Review changes:**
|
||||
- Ensure business logic unchanged
|
||||
- Verify API contracts maintained
|
||||
- Check error handling preserved
|
||||
|
||||
**For React Frontend:**
|
||||
|
||||
1. **Check TypeScript:**
|
||||
```bash
|
||||
npm run type-check
|
||||
```
|
||||
- Ensure no type errors
|
||||
|
||||
2. **Run linter:**
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
- Fix any new linting issues
|
||||
|
||||
3. **Test component:**
|
||||
```bash
|
||||
npm run test:single test/path/to/component.test.tsx
|
||||
```
|
||||
- Verify component behavior unchanged
|
||||
|
||||
4. **Check bundle size:**
|
||||
- Look for improvements in bundle size
|
||||
- Verify lazy loading works
|
||||
|
||||
5. **Manual testing:**
|
||||
- Test component functionality
|
||||
- Verify no regressions
|
||||
- Check loading states
|
||||
- Verify error handling
|
||||
|
||||
### Step 7: Document Changes
|
||||
|
||||
Create summary of optimizations:
|
||||
|
||||
**Changes made:**
|
||||
- List each optimization
|
||||
- Show before/after metrics (if available)
|
||||
- Explain impact of changes
|
||||
|
||||
**Performance improvements:**
|
||||
- Query time reductions
|
||||
- Memory usage improvements
|
||||
- Bundle size reductions
|
||||
- Render time improvements
|
||||
|
||||
**Code quality improvements:**
|
||||
- Better type safety
|
||||
- Reduced duplication
|
||||
- Better separation of concerns
|
||||
- Improved maintainability
|
||||
|
||||
## Common Optimization Patterns
|
||||
|
||||
### C# Backend Patterns
|
||||
|
||||
1. **Repository Pattern with Specification**
|
||||
- Encapsulate query logic
|
||||
- Reusable query specifications
|
||||
- Better testability
|
||||
|
||||
2. **CQRS with MediatR**
|
||||
- Separate read/write operations
|
||||
- Better performance tuning
|
||||
- Cleaner code organization
|
||||
|
||||
3. **Caching Strategy**
|
||||
- In-memory cache for frequent reads
|
||||
- Distributed cache for scalability
|
||||
- Cache invalidation patterns
|
||||
|
||||
4. **Async Best Practices**
|
||||
- Use `async/await` consistently
|
||||
- Avoid `Task.Result` or `.Wait()`
|
||||
- Use `ConfigureAwait(false)` in libraries
|
||||
|
||||
### React Frontend Patterns
|
||||
|
||||
1. **Data Fetching Pattern**
|
||||
- Always use TanStack Query
|
||||
- Implement proper error boundaries
|
||||
- Use suspense for loading states
|
||||
|
||||
2. **Component Composition**
|
||||
- Split large components
|
||||
- Create reusable atoms/molecules
|
||||
- Use compound component pattern
|
||||
|
||||
3. **State Management**
|
||||
- Keep state as local as possible
|
||||
- Use context sparingly
|
||||
- Consider Zustand for global state
|
||||
|
||||
4. **Performance Pattern**
|
||||
- Memoize expensive operations
|
||||
- Use React.memo for pure components
|
||||
- Implement virtualization for long lists
|
||||
|
||||
## Error Handling
|
||||
|
||||
**If build fails after C# optimization:**
|
||||
- Review changes carefully
|
||||
- Check for type mismatches
|
||||
- Verify async/await patterns correct
|
||||
- Rollback if necessary
|
||||
|
||||
**If types break after frontend optimization:**
|
||||
- Check interface definitions
|
||||
- Verify generic types
|
||||
- Update type imports
|
||||
|
||||
**If tests fail after optimization:**
|
||||
- Review test expectations
|
||||
- Update mocks if needed
|
||||
- Verify behavior unchanged
|
||||
|
||||
**If performance degrades:**
|
||||
- Review optimization approach
|
||||
- Check for introduced inefficiencies
|
||||
- Consider alternative approach
|
||||
|
||||
## Important Notes
|
||||
|
||||
- ✅ **Always test after optimization** - Verify functionality unchanged
|
||||
- ✅ **Measure performance** - Use profiling tools to verify improvements
|
||||
- ✅ **Keep it simple** - Don't over-optimize premature code
|
||||
- ✅ **Follow patterns** - Use established patterns from codebase
|
||||
- ⚠️ **Avoid premature optimization** - Focus on actual bottlenecks
|
||||
- ⚠️ **Maintain readability** - Don't sacrifice clarity for minor gains
|
||||
- 📊 **Profile first** - Identify real performance issues before optimizing
|
||||
- 🧪 **Test thoroughly** - Ensure no regressions introduced
|
||||
- 📝 **Document changes** - Explain why optimizations were made
|
||||
|
||||
## Example Execution
|
||||
|
||||
**User input:** `/optimize-current-code`
|
||||
|
||||
**AI execution:**
|
||||
|
||||
1. Identify code type: React component (ProductList.tsx)
|
||||
2. Analyze code: Found useEffect for data fetching, no memoization
|
||||
3. Present plan:
|
||||
- Replace useEffect with TanStack Query
|
||||
- Add React.memo to child components
|
||||
- Extract custom hooks
|
||||
4. Apply optimizations (show diffs)
|
||||
5. Verify: Run type-check and tests
|
||||
6. Summary: "✅ Optimized ProductList component - replaced useEffect with TanStack Query, memoized child components"
|
||||
|
||||
**For C# backend:**
|
||||
|
||||
1. Identify code type: Service class with database operations
|
||||
2. Analyze code: Found N+1 query, missing AsNoTracking, business logic
|
||||
3. Present plan:
|
||||
- Fix N+1 with Include
|
||||
- Add AsNoTracking for read-only
|
||||
- Move business logic to domain
|
||||
4. Apply optimizations
|
||||
5. Verify: Build and test
|
||||
6. Summary: "✅ Optimized OrderService - eliminated N+1 queries, added AsNoTracking, moved business logic to domain layer"
|
||||
|
||||
Reference in New Issue
Block a user