一键导入
performance-optimizer
Optimize application performance including caching, database queries, frontend bundle, and runtime efficiency for gens.team
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Optimize application performance including caching, database queries, frontend bundle, and runtime efficiency for gens.team
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Mission 唯一最终负责人;M0 plan / M1 assess-research / M6 foreword / M7 sign-off 4 个 milestone 全程在场
报告撰稿人;2 种 mode(single-shot / chapter pipeline)+ 3 个 duty(chapter / dimension-outline / mission-outline / single-shot)
Mission 唯一最终负责人;M0 plan / M1 assess-research / M6 foreword / M7 sign-off 4 个 milestone 全程在场
报告撰稿人;2 种 mode(single-shot / chapter pipeline)+ 3 个 duty(chapter / dimension-outline / mission-outline / single-shot)
Manage Git operations, branches, commits, and pull requests following gens.team conventions
Perform comprehensive code reviews for security, performance, maintainability, and best practices
| name | Performance Optimizer |
| description | Optimize application performance including caching, database queries, frontend bundle, and runtime efficiency for gens.team |
| allowed-tools | ["Bash","Read","Write","Edit","Grep","Glob"] |
| tags | ["performance","optimization","caching","database","frontend"] |
You are an expert at optimizing application performance for gens.team.
┌─────────────────────────────────────────────────────────────┐
│ Performance Layers │
├─────────────────────────────────────────────────────────────┤
│ CDN (Vercel Edge) │
│ - Static assets caching │
│ - Edge functions │
├─────────────────────────────────────────────────────────────┤
│ Frontend (Next.js) │
│ - Code splitting - Image optimization │
│ - Tree shaking - Lazy loading │
│ - Bundle analysis - React memo/useMemo │
├─────────────────────────────────────────────────────────────┤
│ API Layer (NestJS) │
│ - Response caching - Compression │
│ - Request batching - Connection pooling │
├─────────────────────────────────────────────────────────────┤
│ Cache Layer (Redis) │
│ - Query results - Session data │
│ - Rate limit counters - Computed values │
├─────────────────────────────────────────────────────────────┤
│ Database (PostgreSQL/MongoDB) │
│ - Query optimization - Indexing │
│ - Connection pooling - Read replicas │
└─────────────────────────────────────────────────────────────┘
# Analyze bundle size
cd frontend && npm run build && npx @next/bundle-analyzer
# Check for large dependencies
npx depcheck
npx bundlephobia <package-name>
// Dynamic imports for route-based splitting
const AiTeamsPage = dynamic(() => import('@/components/ai-teams/AiTeamsPage'), {
loading: () => <PageSkeleton />,
ssr: false, // Disable SSR for heavy client components
});
// Component-level splitting
const HeavyChart = dynamic(() => import('@/components/charts/HeavyChart'), {
loading: () => <ChartSkeleton />,
});
// Conditional loading
const AdminPanel = dynamic(
() => import('@/components/admin/AdminPanel'),
{ ssr: false }
);
// Memoize expensive components
const ResourceCard = memo(function ResourceCard({ resource }: Props) {
return (
<div className="resource-card">
{/* ... */}
</div>
);
}, (prevProps, nextProps) => {
// Custom comparison for deep equality
return prevProps.resource.id === nextProps.resource.id &&
prevProps.resource.updatedAt === nextProps.resource.updatedAt;
});
// Memoize expensive calculations
function ResourceList({ resources, filter }: Props) {
const filteredResources = useMemo(() => {
return resources.filter(r => matchesFilter(r, filter));
}, [resources, filter]);
const sortedResources = useMemo(() => {
return [...filteredResources].sort(compareResources);
}, [filteredResources]);
return <List items={sortedResources} />;
}
// Stable callbacks
function useResourceActions() {
const [resources, setResources] = useState<Resource[]>([]);
const addResource = useCallback((resource: Resource) => {
setResources(prev => [...prev, resource]);
}, []);
const removeResource = useCallback((id: string) => {
setResources(prev => prev.filter(r => r.id !== id));
}, []);
return { resources, addResource, removeResource };
}
// For large lists, use virtualization
import { FixedSizeList } from 'react-window';
function VirtualizedResourceList({ resources }: Props) {
const Row = ({ index, style }: { index: number; style: CSSProperties }) => (
<div style={style}>
<ResourceCard resource={resources[index]} />
</div>
);
return (
<FixedSizeList
height={600}
width="100%"
itemCount={resources.length}
itemSize={80}
>
{Row}
</FixedSizeList>
);
}
// Use Next.js Image component
import Image from 'next/image';
function ResourceImage({ src, alt }: Props) {
return (
<Image
src={src}
alt={alt}
width={400}
height={300}
placeholder="blur"
blurDataURL={generateBlurDataUrl()}
loading="lazy"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
);
}
// Redis caching service
@Injectable()
export class CacheService {
constructor(private redis: Redis) {}
async get<T>(key: string): Promise<T | null> {
const value = await this.redis.get(key);
return value ? JSON.parse(value) : null;
}
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
await this.redis.set(
key,
JSON.stringify(value),
"EX",
ttl || 3600, // Default 1 hour
);
}
async invalidate(pattern: string): Promise<void> {
const keys = await this.redis.keys(pattern);
if (keys.length) {
await this.redis.del(...keys);
}
}
}
// Cache decorator
function Cacheable(ttl: number = 3600) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor,
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const cacheKey = `${propertyKey}:${JSON.stringify(args)}`;
const cacheService = this.cacheService;
const cached = await cacheService.get(cacheKey);
if (cached) {
return cached;
}
const result = await originalMethod.apply(this, args);
await cacheService.set(cacheKey, result, ttl);
return result;
};
return descriptor;
};
}
// Usage
@Injectable()
export class ResourcesService {
@Cacheable(600) // 10 minutes
async getPopularResources(): Promise<Resource[]> {
return this.prisma.resource.findMany({
orderBy: { viewCount: "desc" },
take: 20,
});
}
}
// Efficient queries with Prisma
async getResourcesWithRelations(filter: ResourceFilter) {
return this.prisma.resource.findMany({
where: filter,
select: {
id: true,
title: true,
description: true,
// Only select needed fields
topics: {
select: {
id: true,
name: true,
},
},
},
take: filter.limit || 20,
skip: filter.offset || 0,
});
}
// Use raw queries for complex operations
async getResourceStats(): Promise<ResourceStats> {
return this.prisma.$queryRaw`
SELECT
resource_type,
COUNT(*) as count,
AVG(view_count) as avg_views
FROM resources
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY resource_type
`;
}
// Batch operations
async updateManyResources(updates: ResourceUpdate[]) {
await this.prisma.$transaction(
updates.map(update =>
this.prisma.resource.update({
where: { id: update.id },
data: update.data,
})
)
);
}
-- Create indexes for common queries
CREATE INDEX idx_resources_created_at ON resources(created_at DESC);
CREATE INDEX idx_resources_type_status ON resources(resource_type, status);
CREATE INDEX idx_resources_topic ON resource_topics(topic_id);
-- Composite index for filtered searches
CREATE INDEX idx_resources_search ON resources(status, resource_type, created_at DESC);
-- Full-text search index
CREATE INDEX idx_resources_fulltext ON resources USING gin(to_tsvector('english', title || ' ' || description));
-- Partial index for active records
CREATE INDEX idx_resources_active ON resources(created_at DESC) WHERE status = 'active';
// Prisma connection pooling
// schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
// Connection pool settings
// ?connection_limit=10&pool_timeout=10
}
// MongoDB connection pooling
const mongoClient = new MongoClient(uri, {
maxPoolSize: 50,
minPoolSize: 10,
maxIdleTimeMS: 30000,
waitQueueTimeoutMS: 5000,
});
// Enable compression
import compression from "compression";
app.use(
compression({
filter: (req, res) => {
if (req.headers["x-no-compression"]) {
return false;
}
return compression.filter(req, res);
},
level: 6, // Compression level (1-9)
threshold: 1024, // Only compress responses > 1KB
}),
);
// DataLoader for N+1 query prevention
import DataLoader from "dataloader";
@Injectable()
export class ResourceLoader {
private loader = new DataLoader<string, Resource>(
async (ids) => {
const resources = await this.prisma.resource.findMany({
where: { id: { in: [...ids] } },
});
const resourceMap = new Map(resources.map((r) => [r.id, r]));
return ids.map((id) => resourceMap.get(id) || null);
},
{ cache: true },
);
async load(id: string): Promise<Resource | null> {
return this.loader.load(id);
}
async loadMany(ids: string[]): Promise<(Resource | null)[]> {
return this.loader.loadMany(ids);
}
clear(id: string): void {
this.loader.clear(id);
}
}
// Cursor-based pagination (more efficient)
async getResources(cursor?: string, limit = 20): Promise<PaginatedResponse<Resource>> {
const resources = await this.prisma.resource.findMany({
take: limit + 1, // Fetch one extra to check hasMore
cursor: cursor ? { id: cursor } : undefined,
skip: cursor ? 1 : 0,
orderBy: { createdAt: 'desc' },
});
const hasMore = resources.length > limit;
const items = hasMore ? resources.slice(0, -1) : resources;
const nextCursor = hasMore ? items[items.length - 1].id : null;
return {
items,
nextCursor,
hasMore,
};
}
// Performance monitoring middleware
@Injectable()
export class PerformanceInterceptor implements NestInterceptor {
private readonly logger = new Logger("Performance");
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const start = Date.now();
return next.handle().pipe(
tap(() => {
const duration = Date.now() - start;
const method = request.method;
const url = request.url;
if (duration > 1000) {
this.logger.warn(`SLOW: ${method} ${url} - ${duration}ms`);
}
// Report to metrics service
this.metricsService.recordLatency(method, url, duration);
}),
);
}
}
// Memory profiling
function logMemoryUsage() {
const used = process.memoryUsage();
console.log({
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)} MB`,
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)} MB`,
external: `${Math.round(used.external / 1024 / 1024)} MB`,
rss: `${Math.round(used.rss / 1024 / 1024)} MB`,
});
}
| Area | Optimization | Impact |
|---|---|---|
| Frontend | Code splitting | High |
| Frontend | Image optimization | High |
| Frontend | Virtual scrolling | Medium |
| Frontend | Memoization | Medium |
| Backend | Response caching | High |
| Backend | Query optimization | High |
| Backend | Connection pooling | High |
| Backend | Compression | Medium |
| Database | Proper indexing | Critical |
| Database | Query analysis | High |