Skip to content

sdap: eliminate O(N^2) loop in sdap_add_incomplete_groups()#8454

Merged
alexey-tikhonov merged 1 commit into
SSSD:masterfrom
alexey-tikhonov:initgr-loops-2
Feb 24, 2026
Merged

sdap: eliminate O(N^2) loop in sdap_add_incomplete_groups()#8454
alexey-tikhonov merged 1 commit into
SSSD:masterfrom
alexey-tikhonov:initgr-loops-2

Conversation

@alexey-tikhonov

@alexey-tikhonov alexey-tikhonov commented Feb 16, 2026

Copy link
Copy Markdown
Member

Those patch is based on a profiling of a following test case:

  • users tu1 is a member of 5k LDAP groups (RFC2307 case, no nested groups)
  • SSSD stared with an empty cache
  • time id [email protected] | tr ',' '\n' | wc -l is executed

This patch provides a x2 performance gain for described test case on a laptop. See commit message for details.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request correctly refactors sdap_add_incomplete_groups() to eliminate an O(N^2) loop, replacing it with a more efficient O(N) implementation. This is a great performance improvement. The changes are clean and remove now-unused code and parameters.

I've found one critical issue where loop variables are not being reset, which could lead to data corruption in the cache. Please see my detailed comment.

Comment thread src/providers/ldap/sdap_async_initgroups.c
@alexey-tikhonov
alexey-tikhonov force-pushed the initgr-loops-2 branch 4 times, most recently from 2fa1aa8 to fdd3d17 Compare February 17, 2026 15:21
@alexey-tikhonov alexey-tikhonov removed the coverity Trigger a coverity scan label Feb 17, 2026
@alexey-tikhonov

Copy link
Copy Markdown
Member Author

Note: Covscan is green.

@justin-stephenson justin-stephenson 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.

Changes LGTM, commit message of behavior change is well documented. Thank you.

@sumit-bose sumit-bose 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.

Hi,

thank you for the improvement. I was first a bit irritated testing the patch because I started with 2000 groups and basically didn't seen any improvement. But when I switched to 5000 groups there was a considerable speedup, I didn't reach a factor of 2 but it was near. Code-wise I'm fine, ACK.

Btw, to create a test environment I used a shell script to create an LDIF file with the LDAP content and called dsctl localhost ldif2db userroot /tmp/my.ldif to load it into the LDAP server. While the bash script runs about 20s to create the LDIF, dsctl only took 3s to load 5000 users and 5000 groups. So at least in the pure LDAP case we might not need pre-populated container images but it might be possible to create larger environments on the fly with some optimization to create the LDIF file.

bye,
Sumit

`sdap_add_incomplete_groups()` had two separate steps: first it
iterated the group name list checking each against sysdb to build
a 'missing' list, then for each missing group it scanned the entire
'ldap_groups' array calling to find matching LDAP  attributes.
This resulted in O(N^2) behavior when all groups were missing (i.e.
empty cache).

Replace this with a single O(N) loop that iterates 'ldap_groups'
directly: check sysdb, and if missing create the incomplete entry
immediately.

The 'sysdb_groupnames' parameter is removed as it is not used
anymore.

This patch also has an interesting side effect: it also makes
`sysdb_update_members()` executed in the `sdap_initgr_common_store()`
after `sdap_add_incomplete_groups()` faster. Most probably this
is because previosuly O(N^2) allocations of `groupname` (by
`sdap_get_group_primary_name()`) trashed memory, purging ldb/tdb
data from the cache.

Implementation assisted-by: Claude Code (Opus 4.6)

Reviewed-by: Justin Stephenson <[email protected]>
Reviewed-by: Sumit Bose <[email protected]>
@sssd-bot

Copy link
Copy Markdown
Contributor

The pull request was accepted by @alexey-tikhonov with the following PR CI status:


🟢 CodeQL (success)
🟢 osh-diff-scan:fedora-rawhide-x86_64:upstream (success)
🟢 rpm-build:centos-stream-10-x86_64:upstream (success)
🟢 rpm-build:fedora-42-x86_64:upstream (success)
🟢 rpm-build:fedora-43-x86_64:upstream (success)
🟢 rpm-build:fedora-44-x86_64:upstream (success)
🟢 rpm-build:fedora-rawhide-x86_64:upstream (success)
🟢 Analyze (target) / cppcheck (success)
🟢 Build / freebsd (success)
🟢 Build / make-distcheck (success)
🟢 ci / intgcheck (centos-10) (success)
🟢 ci / intgcheck (fedora-42) (success)
🟢 ci / intgcheck (fedora-43) (success)
🟢 ci / intgcheck (fedora-44) (success)
🟢 ci / intgcheck (fedora-45) (success)
🟢 ci / prepare (success)
🟢 ci / system (centos-10) (success)
🟢 ci / system (fedora-42) (success)
🟢 ci / system (fedora-43) (success)
🔴 ci / system (fedora-44) (failure)
🔴 ci / system (fedora-45) (failure)
➖ Coverity scan / coverity (skipped)
🟢 Static code analysis / codeql (success)
🟢 Static code analysis / pre-commit (success)
🟢 Static code analysis / python-system-tests (success)


There are unsuccessful or unfinished checks. Make sure that the failures are not related to this pull request before merging.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants