Improve perf for worker

This commit is contained in:
2025-11-11 04:09:45 +07:00
parent 1d70355617
commit c6becb032b
2 changed files with 701 additions and 4 deletions

View 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"

View File

@@ -227,6 +227,7 @@ public class BacktestExecutor
// Use optimized rolling window approach - TradingBox.GetSignal only needs last 600 candles
const int rollingWindowSize = 600;
var rollingCandles = new List<Candle>(rollingWindowSize); // Pre-allocate capacity for better performance
var fixedCandlesHashSet = new HashSet<Candle>(rollingWindowSize); // Reuse HashSet to avoid allocations
var candlesProcessed = 0;
// Signal caching optimization - reduce signal update frequency for better performance
@@ -259,10 +260,14 @@ public class BacktestExecutor
if (rollingCandles.Count > rollingWindowSize)
{
// Remove oldest candle (first element) - O(n) but acceptable for small window
// Remove oldest candle from both structures
var removedCandle = rollingCandles[0];
rollingCandles.RemoveAt(0);
fixedCandlesHashSet.Remove(removedCandle);
}
// Add to HashSet for reuse
fixedCandlesHashSet.Add(candle);
tradingBot.LastCandle = candle;
// Smart signal caching - reduce signal update frequency for performance
@@ -276,10 +281,9 @@ public class BacktestExecutor
if (!shouldSkipSignalUpdate)
{
// Convert to HashSet only when needed for GetSignal (it expects HashSet)
var fixedCandles = new HashSet<Candle>(rollingCandles);
// Reuse the pre-allocated HashSet instead of creating new one
var signalUpdateStart = Stopwatch.GetTimestamp();
await tradingBot.UpdateSignals(fixedCandles);
await tradingBot.UpdateSignals(fixedCandlesHashSet);
signalUpdateTotalTime += Stopwatch.GetElapsedTime(signalUpdateStart);
telemetry.TotalSignalUpdates++;
}