.cursor/docs/guides/performance.md
This guide outlines approaches for identifying, analyzing, and resolving performance issues in the Appsmith codebase.
Page Load Time
Rendering Performance
Network Performance
Memory Usage
Response Times
Resource Utilization
Database Performance
Concurrency
Browser DevTools
React DevTools
Lighthouse
Custom Timing
// Performance measurement
performance.mark('start');
// ...code to measure...
performance.mark('end');
performance.measure('operation', 'start', 'end');
console.log(performance.getEntriesByName('operation')[0].duration);
Profilers
Logging and Metrics
Load Testing
Unnecessary Re-renders
Issue:
function Component() {
// This creates a new object on every render
const options = { value: 'example' };
return <ChildComponent options={options} />;
}
Solution:
function Component() {
// Memoize object
const options = useMemo(() => ({ value: 'example' }), []);
return <ChildComponent options={options} />;
}
Unoptimized List Rendering
Issue:
function ItemList({ items }) {
return (
<div>
{items.map(item => (
<Item data={item} />
))}
</div>
);
}
Solution:
function ItemList({ items }) {
return (
<div>
{items.map(item => (
<Item key={item.id} data={item} />
))}
</div>
);
}
// Memoize the Item component
const Item = React.memo(function Item({ data }) {
return <div>{data.name}</div>;
});
Large Bundle Size
Issue:
Solution:
// Before
import { map, filter, reduce } from 'lodash';
// After
import map from 'lodash/map';
import filter from 'lodash/filter';
import reduce from 'lodash/reduce';
// Code splitting with React.lazy
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
Memory Leaks
Issue:
function Component() {
useEffect(() => {
const interval = setInterval(() => {
// Do something
}, 1000);
// No cleanup
}, []);
return <div>Component</div>;
}
Solution:
function Component() {
useEffect(() => {
const interval = setInterval(() => {
// Do something
}, 1000);
// Cleanup
return () => clearInterval(interval);
}, []);
return <div>Component</div>;
}
N+1 Query Problem
Issue:
List<Workspace> workspaces = workspaceRepository.findAll().collectList().block();
for (Workspace workspace : workspaces) {
List<Application> apps = applicationRepository.findByWorkspaceId(workspace.getId()).collectList().block();
workspace.setApplications(apps);
}
Solution:
// Use join query or batch loading
List<Workspace> workspaces = workspaceRepository.findAllWithApplications().collectList().block();
Missing Database Indexes
Issue:
// Query without proper index
Mono<User> findByEmail(String email);
Solution:
// Add index to database
@Document(collection = "users")
public class User {
@Indexed(unique = true)
private String email;
// ...
}
Blocking Operations in Reactive Streams
Issue:
return Mono.fromCallable(() -> {
// Blocking file I/O operation
return Files.readAllBytes(Paths.get("path/to/file"));
});
Solution:
return Mono.fromCallable(() -> {
// Blocking file I/O operation
return Files.readAllBytes(Paths.get("path/to/file"));
}).subscribeOn(Schedulers.boundedElastic());
Inefficient Data Processing
Issue:
// Processing large amounts of data in memory
return repository.findAll()
.collectList()
.map(items -> {
// Process all items at once
return items.stream().map(this::transform).collect(Collectors.toList());
});
Solution:
// Stream processing with backpressure
return repository.findAll()
.map(this::transform)
.collectList();