Skip to content
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

Fix regression in JdkMapAdapterStringMap performance #2256

Merged
merged 3 commits into from
Feb 5, 2024

Conversation

ppkarwasz
Copy link
Contributor

@ppkarwasz ppkarwasz commented Jan 29, 2024

We introduce a new constructor for JdkMapAdapterStringMap to prevent the performance penalty of an exception if the map is immutable. The regression was introduced in #2101.

Closes #2238.

@ppkarwasz ppkarwasz added this to the 2.23.0 milestone Jan 29, 2024
@ppkarwasz ppkarwasz self-assigned this Jan 29, 2024
@ppkarwasz ppkarwasz requested review from rgoers and jvz January 29, 2024 19:52
Copy link
Member

@vy vy left a comment

Choose a reason for hiding this comment

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

Thanks so much for promptly handling this. I guess this warrants a quick 2.23.0 release.

Changes LGTM. But I am not feeling confident enough to say we addressed the problem. I don't see a test triggering the code path users reported. Can you add such a test, please? Maybe we can craft/mock a custom map throwing an [unexpected] exception on replace() and verify that replace() is not called?

Comment on lines -64 to +98
return map;
return new HashMap<>(map);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change is required by the toMap contract, which requires a "mutable snapshot of the underlying data".

@rgoers
Copy link
Member

rgoers commented Jan 31, 2024

This seems strange to me. Why wouldn't you create an ImmutableJdkMapAdapterStringMap that extends JdkMapAdapterStringMap (or vice versa) instead of using a boolean parameter? It seems like it would be cleaner.

@ppkarwasz
Copy link
Contributor Author

ppkarwasz commented Jan 31, 2024

@rgoers,

This seems strange to me. Why wouldn't you create an ImmutableJdkMapAdapterStringMap that extends JdkMapAdapterStringMap (or vice versa) instead of using a boolean parameter? It seems like it would be cleaner.

The original problem in #2098 was that a user implemented ContextDataProvider#supplyContextData using Map#of. This caused the generation of a StringMap that wasn't frozen, but wasn't modifiable either, since the underlying map was immutable.

I tried auto-detecting the problem which caused the performance issue we are facing today. By adding a new constructor I want to give users clear directions that:

  • if the provided map is not immutable, Log4j might reuse it to prevent the allocation of new instances,
  • if the provided map is immutable, it must be marked so.

I can create an ImmutableJdkMapAdapterStringMap, but then the contract of the original JdkMapAdapterStringMap constructor must be changed. What do you think?

We introduce a new constructor for `JdkMapAdapterStringMap` to prevent
the performance penalty of an exception if the map is immutable.
@ppkarwasz ppkarwasz merged commit 75ed23a into main Feb 5, 2024
5 of 6 checks passed
@ppkarwasz ppkarwasz deleted the fix/2238_fix_jdk_string_map branch February 5, 2024 21:55
@ppkarwasz ppkarwasz removed this from the 2.23.0 milestone Feb 5, 2024
@ppkarwasz
Copy link
Contributor Author

@rgoers,

I think that an entire ImmutableJdkMapAdapterStringMap class is a little bit overkill for this, but maybe a pair of factory methods would be more appropriate (IDEA complains that boolean in a constructor is bad practice).
Any idea how to call them? createMutable and createFrozen?

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.

None yet

3 participants