Skip to content

feat: [performance improvement] optimize getSpeakerByYearAndId with Map lookup#297

Open
anyulled wants to merge 2 commits into
mainfrom
feat/performance-getspeaker-map-17360583596143430945
Open

feat: [performance improvement] optimize getSpeakerByYearAndId with Map lookup#297
anyulled wants to merge 2 commits into
mainfrom
feat/performance-getspeaker-map-17360583596143430945

Conversation

@anyulled

@anyulled anyulled commented Jun 26, 2026

Copy link
Copy Markdown
Owner

💡 What: Replaced array .find() with a Map lookup in getSpeakerByYearAndId.
🎯 Why: Replaced an O(N) lookup with an O(1) Map lookup.
📊 Impact: Converts the amortized time complexity of fetching speaker details to O(1), improving render performance.
🔬 Measurement: Observe reduction in array traversal times during page renders.


PR created automatically by Jules for task 17360583596143430945 started by @anyulled

Summary by CodeRabbit

  • New Features
    • Improved speaker lookup performance when loading speaker details, resulting in faster responses for repeated queries.
    • Added documentation guidance for optimizing repeated data fetches in the app.

…ap lookup

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
devbcn-nextjs Error Error Jun 26, 2026 8:35am

Request Review

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@anyulled, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 52 minutes and 57 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cbc7c9b3-267e-4c8d-9973-d0e8457b89e1

📥 Commits

Reviewing files that changed from the base of the PR and between edfbd67 and 565685f.

📒 Files selected for processing (1)
  • .jules/bolt.md
📝 Walkthrough

Walkthrough

getSpeakerByYearAndId now resolves speakers through a cached yearly Map instead of scanning an array. A short note was added describing the lookup strategy and React cache() usage.

Changes

Speaker lookup optimization

Layer / File(s) Summary
Cached speaker map lookup
hooks/useSpeakers.ts, .jules/bolt.md
getSpeakersMap(year) builds a cached Map from yearly speakers, getSpeakerByYearAndId uses Map.get(...), and the note documents the lookup pattern and cache() usage.

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • anyulled/devbcn-nextjs#152: Also changes speaker data access from repeated linear scans to O(1)-style keyed lookup in hook code.

Poem

🐰 I hopped through speakers, row by row,
Then found a Map to make it go!
No more long scans in dusty lines,
Just quick little hops and tidy signs.
My ears are up, my code is bright—
Fast little rabbits do love a Map delight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing getSpeakerByYearAndId array scanning with a Map lookup for performance.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/performance-getspeaker-map-17360583596143430945

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 optimizes the getSpeakerByYearAndId function by introducing a cached Map lookup instead of performing an O(n) array traversal with .find(), and documents this pattern in .jules/bolt.md. The review feedback recommends avoiding intermediate array allocations when constructing the Map by using a loop instead of .map() in both the implementation and the documentation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread hooks/useSpeakers.ts
Comment on lines +38 to +41
const getSpeakersMap = cache(async (year: string | number): Promise<Map<string, Speaker>> => {
const speakers = await getSpeakers(year);
return speakers.find((speaker) => speaker.id === speakerId);
return new Map(speakers.map((speaker) => [speaker.id, speaker]));
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While using a Map lookup is a great O(1) optimization, using speakers.map(...) inside the Map constructor creates an intermediate array of [key, value] tuples for every speaker. This introduces unnecessary memory allocations and garbage collection overhead, which contradicts the optimization principles documented in .jules/bolt.md (e.g., avoiding unnecessary allocations).

We can construct the Map using a simple loop to avoid any intermediate array allocations.

const getSpeakersMap = cache(async (year: string | number): Promise<Map<string, Speaker>> => {
  const speakers = await getSpeakers(year);
  const speakersMap = new Map<string, Speaker>();
  for (const speaker of speakers) {
    speakersMap.set(speaker.id, speaker);
  }
  return speakersMap;
});

Comment thread .jules/bolt.md

## 2024-06-26 — Optimize getSpeakerByYearAndId with Map Lookups
**Learning:** In a codebase frequently querying speaker configurations (like via `getSpeakerByYearAndId`), standard array traversals via `.find()` introduce O(n) amortized overhead upon multiple lookups.
**Action:** Always wrap lists generated from repeated queries in a React `cache()` wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To align with the goal of minimizing memory allocations and GC overhead (as noted in the first learning entry), we should avoid using arr.map(a => [a.id, a]) when constructing the Map. This creates N intermediate tuple arrays. Instead, we should recommend populating the Map using a loop or forEach.

Suggested change
**Action:** Always wrap lists generated from repeated queries in a React `cache()` wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.
**Action:** Always wrap lists generated from repeated queries in a React cache() wrapped generic map generator (e.g. populate a new Map via a loop) to facilitate amortized O(1) property access without intermediate array allocations.

…ap lookup

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.jules/bolt.md:
- Line 8: The note wording in the guidance should use the compound modifier
“cache()-wrapped” for clarity. Update the text referenced by the repeated-query
map generator instruction so that the phrase around React cache usage reads as
“React `cache()`-wrapped generic map generator,” keeping the rest of the
guidance unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 26c6eabf-7c31-4205-a1ca-845642fada54

📥 Commits

Reviewing files that changed from the base of the PR and between df1657d and edfbd67.

📒 Files selected for processing (2)
  • .jules/bolt.md
  • hooks/useSpeakers.ts

Comment thread .jules/bolt.md

## 2024-06-26 — Optimize getSpeakerByYearAndId with Map Lookups
**Learning:** In a codebase frequently querying speaker configurations (like via `getSpeakerByYearAndId`), standard array traversals via `.find()` introduce O(n) amortized overhead upon multiple lookups.
**Action:** Always wrap lists generated from repeated queries in a React `cache()` wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Hyphenate cache()-wrapped in the note.

Line 8 reads cleaner as a compound modifier, e.g. React `cache()`-wrapped generic map generator.

Suggested edit
-**Action:** Always wrap lists generated from repeated queries in a React `cache()` wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.
+**Action:** Always wrap lists generated from repeated queries in a React `cache()`-wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**Action:** Always wrap lists generated from repeated queries in a React `cache()` wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.
**Action:** Always wrap lists generated from repeated queries in a React `cache()`-wrapped generic map generator (e.g. `const map = new Map(arr.map(a => [a.id, a]))`) to facilitate amortized O(1) property access.
🧰 Tools
🪛 LanguageTool

[grammar] ~8-~8: Use a hyphen to join words.
Context: ...om repeated queries in a React cache() wrapped generic map generator (e.g. `con...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.jules/bolt.md at line 8, The note wording in the guidance should use the
compound modifier “cache()-wrapped” for clarity. Update the text referenced by
the repeated-query map generator instruction so that the phrase around React
cache usage reads as “React `cache()`-wrapped generic map generator,” keeping
the rest of the guidance unchanged.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant