Skip to content

CDRIVER-5864 Do not parse BSON in mongoc_server_description_new_copy #1835

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

Merged
merged 5 commits into from
Feb 4, 2025

Conversation

kevinAlbs
Copy link
Collaborator

@kevinAlbs kevinAlbs commented Jan 27, 2025

This PR is intended to improve performance of mongoc_server_description_new_copy. Rather than re-parse the BSON document of the hello reply each time, fields are copied over individually. Internal references into the BSON document are copied by calculating the offset into the BSON document.

Atomic modification to round_trip_time_msec is removed. round_trip_time_msec appears to only be modified with exclusive access to the mongoc_server_description_t (when applying in mongoc_server_description_handle_hello, or modifying the topology description).

mongoc_server_description_new_copy now assigns each field in the order declared in mongoc_server_description_t to more easily cross-reference.

Verified with this patch build: https://spruce.mongodb.com/version/67938f122a38d700078e6820

Background & Motivation

HELP-69502 notes an observed performance regression from CDRIVER-4114. ded9ae5 trades a lock-and-modify with a copy-modify-and-swap to avoid lock contention on the shared topology description. Neither I nor support has yet been able to reproduce the same slowdown. But a shared flamegraph shows many samples in mongoc_server_description_new_copy.

Running a benchmark calling mongoc_server_description_new_copy 120 times shows promising results:

On commit ded9ae5:

[       OK ] mongoc_server_description_new_copy.sdcopy (mean 420.852us, confidence interval +- 1.644652%)

On this branch:

[       OK ] mongoc_server_description_new_copy.sdcopy (mean 27.859us, confidence interval +- 1.462177%)

@kevinAlbs kevinAlbs marked this pull request as ready for review January 27, 2025 13:17
@kevinAlbs kevinAlbs requested review from vector-of-bool and a user January 27, 2025 13:17
@kevinAlbs kevinAlbs changed the title Do not parse BSON in mongoc_server_description_new_copy CDRIVER-5864 Do not parse BSON in mongoc_server_description_new_copy Jan 27, 2025
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Nice change! I like the approach, and it's good to see the improvements in microbenchmark results.


#define COPY_BSON_FIELD(FIELD) \
if (1) { \
bson_init (&copy->FIELD); \
Copy link

Choose a reason for hiding this comment

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

This init could be omitted, bson_copy_to doesn't require the destination to be initialized.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good spot. Updated.

if (1) { \
if (!bson_empty (&description->FIELD)) { \
ptrdiff_t offset = bson_get_data (&description->FIELD) - bson_get_data (&description->last_hello_response); \
const uint8_t *data = bson_get_data (&copy->last_hello_response) + offset; \
Copy link

Choose a reason for hiding this comment

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

I know this is a performance patch, but it might still be worth bounds-checking 'offset' here? This might be a good place for a debug-only or asan-only assertion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added debug-only assertions with MONGOC_DEBUG_ASSERT

#define COPY_INTERNAL_STRING_FIELD(FIELD) \
if (1) { \
if (description->FIELD) { \
ptrdiff_t offset = (char *) description->FIELD - (char *) bson_get_data (&description->last_hello_response); \
Copy link

Choose a reason for hiding this comment

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

This might be a good place for an asan-only assertion too, since it would require a heavy strlen check.

Copy link
Contributor

@vector-of-bool vector-of-bool left a comment

Choose a reason for hiding this comment

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

LGTM.

Since the i64 atomics appears to be a bottleneck, I would assume that this was only showing up on 32-bit builds? On 64-bit systems it shouldn't need to use the emulated atomics. If they are building on 64bit and still getting the emulated atomics, I'd be concerned that our atomic-detection may be broken.

@kevinAlbs
Copy link
Collaborator Author

Since the i64 atomics appears to be a bottleneck, I would assume that this was only showing up on 32-bit builds?

I think the atomics were a red herring. The build was 64-bit. And I expect it was using the atomic intrinsics. Testing a branch with only the atomics removed did not show much improvement.

@kevinAlbs kevinAlbs merged commit 0f7fcad into mongodb:master Feb 4, 2025
45 checks passed
kevinAlbs added a commit that referenced this pull request Feb 4, 2025
#1835)

* do not parse BSON in `mongoc_server_description_new_copy`

* remove unnecessary atomic modification of `round_trip_time_msec`

* add tests for copying
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