Skip to content

Reuse cached GitHub organization members when building role groups - #304

Open
hosom wants to merge 1 commit into
mainfrom
hosom/reuse-github-org-members
Open

Reuse cached GitHub organization members when building role groups#304
hosom wants to merge 1 commit into
mainfrom
hosom/reuse-github-org-members

Conversation

@hosom

@hosom hosom commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Read the cached GitHub organization membership hash once when constructing a role group instead of retrieving it once per username.

Problem

GitHubOrg::Provider#role_to_group currently does this:

members = github.org_members.keys.select { |username| github.org_members[username] == role }

org_members has a HashOf[String => String] return contract. Although the underlying data is cached, every accessor call deeply validates all keys and values. Calling the accessor once per username therefore amplifies an O(n) operation into O(n²) validation and allocation work.

A live github/entitlements CPU profile attributed:

  • 42.0% total CPU to Contracts::Builtin::HashOf#valid?
  • 79.8% total CPU beneath Contracts::CallWith#call_with_inner
  • 16.9% of samples to GC

The dominant HashOf stack was GitHubOrg::Provider#readrole_to_grouporg_members.

Fix

Capture org_members once and select matching hash entries in one traversal:

org_members = github.org_members
members = org_members.select { |_, member_role| member_role == role }.keys

This preserves the existing return contract and output while reducing deep membership-hash validation to once per role group. The regression test now requires exactly one org_members call.

Validation

  • 189 unit examples, 0 failures
  • 100% unit coverage
  • RuboCop on changed files, no offenses
  • git diff --check

A locally built gem from this PR will be tested in the production-shaped github/entitlements benchmark PR to measure the live impact.

Read the organization membership hash once while constructing a role group. This avoids repeatedly executing the deep HashOf return contract for every username in the organization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5b8ed060-ed02-4402-b5e1-af407bcb2f61
Copilot AI balanced review requested due to automatic review settings September 11, 2026 23:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved review issues were identified.

Review tier: Lite (auto)
Findings: None

Note

Copilot is running an experiment and ran this review at Lite.

What changed in this PR

Optimizes GitHub organization role-group construction by reading the cached membership hash once.

Changes:

  • Reuses one org_members result during filtering.
  • Strengthens the regression test to require exactly one lookup.
File Description
spec/​unit/​entitlements/​backend/​github_org/​provider_spec.rb Verifies org_members is accessed once.
lib/​entitlements/​backend/​github_org/​provider.rb Filters members through a single hash traversal.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@hosom

hosom commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

Live production-shaped confirmation

A local gem built from this PR was vendored alongside github/entitlements-app#78 in github/entitlements#141320.

CPU profile

Direct StackProf comparison using the same 1ms CPU profiler:

Metric Before this PR With this PR Change
Total CPU samples 194,071 93,125 -52.0%
HashOf#valid? self samples 34,349 802 -97.7%
HashOf#valid? total samples 81,471 1,939 -97.6%
Array#map self samples 32,203 1,452 -95.5%
Contract.valid? self samples 10,742 337 -96.9%
CallWith#call_with_inner total samples 154,808 68,586 -55.7%
GC samples 32,864 18,541 -43.6%

HashOf#valid? fell from 17.7% self / 42.0% total CPU to 0.9% self / 2.1% total CPU. This confirms the repeated org_members accessor was the source of the dominant deep-validation profile.

Unprofiled calculation timing

Configuration Runs Average
entitlements-app #78 only 494.56s, 495.87s 495.22s
+ this provider PR 509.46s, 457.02s 483.24s

The average end-to-end calculation improvement is 11.98s / 2.4%. Wall time remains noisy because GitHub, AAD, LDAP, and cache I/O occur within the calculation phase, but the CPU profile isolates and confirms the intended optimization.

All provider repository CI checks, including acceptance tests, are green.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants