URL: https://github.com/SSSD/sssd/pull/5937 Author: alexey-tikhonov Title: #5937: [WIP] Another attempt to resolve #5134 Action: opened
PR body: """ There are two ideas: - get rid of re-alloc for every new member added: instead reserve space with a margin and shrink later. - don't add every new member to the list immediately: instead keep new members in a temporarily hash table. This will allow to avoid cross strcmp() at least among new members - hopefully, hash table should be much faster. 2nd patch actually makes 1st patch obsolete, but I will keep it a while to measure impact. This is "WIP" as I didn't conduct perf measurements yet. """ To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/5937/head:pr5937 git checkout pr5937
From 1557e7f31216919c6f7170d6d503927827e95280 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Tue, 28 Dec 2021 23:04:45 +0100 Subject: [PATCH 1/3] SDAP: sdap_nested_group_deref_direct_process(): avoid realloc for every new member. Single realloc + shrink are much cheaper. --- src/providers/ldap/sdap_async_nested_groups.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c index 2570a00bbd..577353569c 100644 --- a/src/providers/ldap/sdap_async_nested_groups.c +++ b/src/providers/ldap/sdap_async_nested_groups.c @@ -2334,6 +2334,15 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) goto done; } + /* The same with new members: make an assumpation all entries are new + and shrink memory later. */ + members->values = talloc_realloc(members, members->values, struct ldb_val, + members->num_values + num_entries); + if (members->values == NULL) { + ret = ENOMEM; + goto done; + } + PROBE(SDAP_NESTED_GROUP_DEREF_PROCESS_PRE); for (i = 0; i < num_entries; i++) { ret = sysdb_attrs_get_string(entries[i]->attrs, @@ -2362,14 +2371,6 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) /* Append newly found member to member list. * Changes in state->members will propagate into sysdb_attrs of * the group. */ - state->members->values = talloc_realloc(members, members->values, - struct ldb_val, - members->num_values + 1); - if (members->values == NULL) { - ret = ENOMEM; - goto done; - } - members->values[members->num_values].data = (uint8_t *)talloc_strdup(members->values, orig_dn); if (members->values[members->num_values].data == NULL) { @@ -2452,6 +2453,13 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) talloc_zfree(state->nested_groups); } + members->values = talloc_realloc(members, members->values, struct ldb_val, + members->num_values); + if (members->values == NULL) { + ret = ENOMEM; + goto done; + } + ret = EOK; done: From 9cf6a1c868de1b91a2f6f038cbb88cde303f0ce2 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Wed, 29 Dec 2021 21:04:26 +0100 Subject: [PATCH 2/3] SDAP: sdap_nested_group_deref_direct_process(): don't add all new members to the list immediately to avoid cross strcasecmp() amongst them. Resolves: https://github.com/SSSD/sssd/issues/5134 --- src/providers/ldap/sdap_async_nested_groups.c | 89 ++++++++++++++----- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c index 577353569c..4c89542b12 100644 --- a/src/providers/ldap/sdap_async_nested_groups.c +++ b/src/providers/ldap/sdap_async_nested_groups.c @@ -2293,6 +2293,49 @@ sdap_nested_group_deref_send(TALLOC_CTX *mem_ctx, return req; } +static errno_t +expand_members_list(struct ldb_message_element *members, hash_table_t *addon) +{ + struct hash_iter_context_t *iter; + hash_entry_t *entry; + const char *dn; + unsigned long num_new_members = hash_count(addon); + + if (num_new_members == 0) { + return EOK; + } + + members->values = talloc_realloc(members, members->values, struct ldb_val, + members->num_values + num_new_members); + if (members->values == NULL) { + return ENOMEM; + } + + iter = new_hash_iter_context(addon); + if (iter == NULL) { + return ENOMEM; + } + + while ((entry = iter->next(iter)) != NULL) { + if (entry->key.type != HASH_KEY_CONST_STRING) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Unexpected key type = %d\n", entry->key.type); + continue; + } + dn = entry->key.c_str; + members->values[members->num_values].data = + (uint8_t *)talloc_strdup(members->values, dn); + if (members->values[members->num_values].data == NULL) { + return ENOMEM; + } + members->values[members->num_values].length = strlen(dn); + members->num_values++; + } + talloc_free(iter); + + return EOK; +} + static errno_t sdap_nested_group_deref_direct_process(struct tevent_req *subreq) { @@ -2306,6 +2349,9 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) size_t num_entries = 0; size_t i, j; bool member_found; + hash_table_t *new_members; /* will be used as a set */ + hash_key_t key; + hash_value_t value; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); @@ -2319,6 +2365,14 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) goto done; } + ret = sss_hash_create(state, 0, &new_members); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n", + ret, strerror(ret)); + new_members = NULL; + goto done; + } + DEBUG(SSSDBG_TRACE_INTERNAL, "Received %zu dereference results, " "about to process them\n", num_entries); @@ -2334,15 +2388,6 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) goto done; } - /* The same with new members: make an assumpation all entries are new - and shrink memory later. */ - members->values = talloc_realloc(members, members->values, struct ldb_val, - members->num_values + num_entries); - if (members->values == NULL) { - ret = ENOMEM; - goto done; - } - PROBE(SDAP_NESTED_GROUP_DEREF_PROCESS_PRE); for (i = 0; i < num_entries; i++) { ret = sysdb_attrs_get_string(entries[i]->attrs, @@ -2359,7 +2404,6 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) */ member_found = false; for (j = 0; j < members->num_values; j++) { - /* FIXME: This is inefficient for very large sets of groups */ member_dn = (const char *)members->values[j].data; if (strcasecmp(orig_dn, member_dn) == 0) { member_found = true; @@ -2368,18 +2412,17 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) } if (!member_found) { - /* Append newly found member to member list. + /* Store newly found member to append to member list later. * Changes in state->members will propagate into sysdb_attrs of * the group. */ - members->values[members->num_values].data = - (uint8_t *)talloc_strdup(members->values, orig_dn); - if (members->values[members->num_values].data == NULL) { - ret = ENOMEM; - goto done; + key.type = HASH_KEY_CONST_STRING; + key.c_str = orig_dn; + value.type = HASH_VALUE_UNDEF; + ret = hash_enter(new_members, &key, &value); + if (ret != HASH_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to add '%s' to member list\n", orig_dn); } - - members->values[members->num_values].length = strlen(orig_dn); - members->num_values++; } if (entries[i]->map == opts->user_map) { @@ -2453,16 +2496,16 @@ sdap_nested_group_deref_direct_process(struct tevent_req *subreq) talloc_zfree(state->nested_groups); } - members->values = talloc_realloc(members, members->values, struct ldb_val, - members->num_values); - if (members->values == NULL) { - ret = ENOMEM; + ret = expand_members_list(members, new_members); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "expand_members_list() failed: %d\n", ret); goto done; } ret = EOK; done: + hash_destroy(new_members); return ret; } From a0d2a0bbc1003402c36a58e831da3de3e24927f5 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Wed, 29 Dec 2021 21:21:33 +0100 Subject: [PATCH 3/3] SDAP: sdap_nested_group_hash_insert(): don't create key copy - hash_enter() takes care of this. --- src/providers/ldap/sdap_async_nested_groups.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c index 4c89542b12..16e1658991 100644 --- a/src/providers/ldap/sdap_async_nested_groups.c +++ b/src/providers/ldap/sdap_async_nested_groups.c @@ -209,13 +209,9 @@ static errno_t sdap_nested_group_hash_insert(hash_table_t *table, entry_key, table_name); key.type = HASH_KEY_STRING; - key.str = talloc_strdup(NULL, entry_key); - if (key.str == NULL) { - return ENOMEM; - } + key.c_str = discard_const(entry_key); /* hash_enter() will make a copy */ if (overwrite == false && hash_has_key(table, &key)) { - talloc_free(key.str); return EEXIST; } @@ -224,11 +220,9 @@ static errno_t sdap_nested_group_hash_insert(hash_table_t *table, hret = hash_enter(table, &key, &value); if (hret != HASH_SUCCESS) { - talloc_free(key.str); return EIO; } - talloc_steal(table, key.str); talloc_steal(table, value.ptr); return EOK;
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure