Avoid performing expensive operations repeatedly, especially in hot code paths. Identify operations such as parsing, deserialization, or configuration lookups that can be done once and reused.
Three key strategies:
// Optimized: Parse once during initialization func newWorkerQueryEngine(nsID string, query string) *workerQueryEngine { parsedQuery, _ := prepareQuery(query) // Parse once return &workerQueryEngine{ nsID: nsID, query: query, parsedQuery: parsedQuery, } }
2. **Cache expensive results**:
```go
// Add a TODO for caching deserialized tasks
taskValue, err := deserializeTask(registrableTask, taskInfo.Data)
// TODO: Cache the deserialized task to avoid repeated deserialization
// Efficient: Returns pointer to existing data return &cvs[idx], nil // Returns pointer into slice, avoiding allocation
4. **Calculate values once and pass as parameters**:
```go
// Inefficient: Repeatedly evaluating expensive config
for _, start := range starts {
if e.shouldYield(scheduler, *actionsTaken) { // Config lookup each time
break
}
// ...
}
// Efficient: Calculate once and reuse
tweakables := e.Config.Tweakables(scheduler.Namespace)
maxActions := tweakables.MaxActionsPerExecution
for _, start := range starts {
if *actionsTaken >= maxActions {
break
}
// ...
}
Also consider proper ordering of operations - perform cheap checks before expensive ones. For example, check exclusion conditions before making dynamic config calls.
Enter the URL of a public GitHub repository