-
Notifications
You must be signed in to change notification settings - Fork 246
chore(sequencers): optimize store check #2945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest Buf updates on your PR. Results from workflow CI / buf-check (pull_request).
|
Summary of ChangesHello @julienrbrt, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request focuses on optimizing the retrieval of the Data Availability (DA) start height within the sequencer. By implementing an in-memory cache, the system can now avoid unnecessary database lookups for this frequently accessed value, leading to improved performance and more efficient state management. The change also includes a minor refactoring to better integrate the retrieval logic with the Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Claude finished @julienrbrt's task in 1m 19s —— View job Code Review CompleteI've analyzed the optimization in this PR. Here's my comprehensive review: SummaryThis PR introduces an in-memory cache for Positive Observations1. Performance Optimization ✓
2. Code Quality ✓
3. Correctness ✓
Areas for Consideration1. Cache Invalidation Strategy The current implementation assumes // In getInitialDAStartHeight
if daStartHeight := c.daStartHeight.Load(); daStartHeight != 0 {
return daStartHeight
}Issue: If the cached value is
Recommendation: Consider using a separate boolean flag or a pointer to distinguish between "not initialized" and "initialized to 0": type Sequencer struct {
// ...
daStartHeight atomic.Uint64
daStartHeightCached atomic.Bool // Track if value has been loaded
}
func (c *Sequencer) getInitialDAStartHeight(ctx context.Context) uint64 {
if c.daStartHeightCached.Load() {
return c.daStartHeight.Load()
}
s := store.New(store.NewEvNodeKVStore(c.db))
daIncludedHeightBytes, err := s.GetMetadata(ctx, store.GenesisDAHeightKey)
var daStartHeight uint64
if err == nil && len(daIncludedHeightBytes) == 8 {
daStartHeight = binary.LittleEndian.Uint64(daIncludedHeightBytes)
}
c.daStartHeight.Store(daStartHeight)
c.daStartHeightCached.Store(true)
return daStartHeight
}However, if 2. Race Condition (Minor) There's a theoretical TOCTOU (time-of-check-time-of-use) race in if daStartHeight := c.daStartHeight.Load(); daStartHeight != 0 {
return daStartHeight // Fast path
}
// Slow path: multiple goroutines could execute this simultaneously
s := store.New(store.NewEvNodeKVStore(c.db))
daIncludedHeightBytes, err := s.GetMetadata(ctx, store.GenesisDAHeightKey)
// ...
c.daStartHeight.Store(daStartHeight)Impact: If multiple goroutines call Recommendation: If this is a hot path during initialization, consider using type Sequencer struct {
// ...
daStartHeight atomic.Uint64
daStartHeightOnce sync.Once
}
func (c *Sequencer) getInitialDAStartHeight(ctx context.Context) uint64 {
c.daStartHeightOnce.Do(func() {
if daStartHeight := c.daStartHeight.Load(); daStartHeight != 0 {
return // Already initialized from genesis
}
s := store.New(store.NewEvNodeKVStore(c.db))
daIncludedHeightBytes, err := s.GetMetadata(ctx, store.GenesisDAHeightKey)
if err == nil && len(daIncludedHeightBytes) == 8 {
c.daStartHeight.Store(binary.LittleEndian.Uint64(daIncludedHeightBytes))
}
})
return c.daStartHeight.Load()
}Note: This requires careful handling since 3. Documentation Consider adding a comment to the // daStartHeight caches the DA height from genesis to avoid repeated store lookups.
// Initialized from genesis.DAStartHeight and updated from store on first access if needed.
daStartHeight atomic.Uint64Testing Recommendations
VerdictApproved with minor suggestions. The optimization is effective and the implementation is correct for the common case. The suggestions above are for edge case handling and could be addressed in a follow-up if deemed necessary. The code follows Go idioms, uses appropriate concurrency primitives, and provides a measurable performance improvement without introducing correctness issues. Impact: Reduced database I/O, improved performance for forced inclusion transaction retrieval paths. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces an optimization to cache the initial DA start height, avoiding repeated lookups from the store. A new atomic field daStartHeight is added to the Sequencer struct, and the getInitialDAStartHeight function is converted to a method that implements read-through caching. The change is logical and addresses the goal of checking the store only once. However, the current implementation of the caching logic in getInitialDAStartHeight has a race condition that could lead to multiple database reads under concurrent access. I've left a comment with a suggestion to address this.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2945 +/- ##
==========================================
- Coverage 59.18% 59.15% -0.04%
==========================================
Files 90 90
Lines 8627 8632 +5
==========================================
Hits 5106 5106
- Misses 2940 2944 +4
- Partials 581 582 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
alpe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Overview
Small improvement to check da inclusion store once.