Skip to content

Conversation

@lhotari
Copy link
Member

@lhotari lhotari commented Jan 9, 2023

Motivation

Creating a Jackson ObjectMapper is an expensive operation. A thread local ObjectMapper instance is already used in most locations.

Additional motivation is to be able to use a properly configured ObjectMapper instance with Jackson Java 8 modules. That PR is #19161 .

Modifications

  • Make use of shared ObjectMapper instances.
  • Remove the ThreadLocal ObjectMapper instances and replace with a global singleton instance
    • In some old versions of Jackson there was a performance benefit of using a ThreadLocal instance. This isn't necessary with the Jackson version that is used.

Documentation

  • doc
  • doc-required
  • doc-not-needed
  • doc-complete

Matching PR in forked repository

PR in forked repository: lhotari#124

@lhotari lhotari added this to the 2.12.0 milestone Jan 9, 2023
@lhotari lhotari self-assigned this Jan 9, 2023
@lhotari lhotari force-pushed the lh-use-thread-local-ObjectMapper branch from c8ef4d8 to 05ef22c Compare January 9, 2023 09:44
@github-actions github-actions bot added the doc-not-needed Your PR changes do not impact docs label Jan 9, 2023
@lhotari lhotari force-pushed the lh-use-thread-local-ObjectMapper branch from 05ef22c to 10772b8 Compare January 9, 2023 09:51
@Technoboy- Technoboy- closed this Jan 9, 2023
@Technoboy- Technoboy- reopened this Jan 9, 2023
@Technoboy- Technoboy- changed the title [improve][common] Use ThreadLocal Jackson ObjectMapper to reduce overhead [improve][misc] Use ThreadLocal Jackson ObjectMapper to reduce overhead Jan 9, 2023
@codecov-commenter
Copy link

codecov-commenter commented Jan 9, 2023

Codecov Report

Merging #19160 (ea2b23f) into master (d7f8f56) will decrease coverage by 0.52%.
The diff coverage is 56.56%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master   #19160      +/-   ##
============================================
- Coverage     47.89%   47.36%   -0.53%     
+ Complexity    10871    10729     -142     
============================================
  Files           713      713              
  Lines         69730    69723       -7     
  Branches       7496     7497       +1     
============================================
- Hits          33394    33024     -370     
- Misses        32631    32974     +343     
- Partials       3705     3725      +20     
Flag Coverage Δ
unittests 47.36% <56.56%> (-0.53%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...che/bookkeeper/mledger/offload/OffloaderUtils.java 1.47% <0.00%> (ø)
.../org/apache/pulsar/broker/admin/v2/Namespaces.java 56.50% <0.00%> (-3.58%) ⬇️
...ulsar/broker/intercept/BrokerInterceptorUtils.java 10.71% <0.00%> (ø)
.../broker/loadbalance/impl/PulsarLoadReportImpl.java 0.00% <0.00%> (ø)
...e/pulsar/broker/protocol/ProtocolHandlerUtils.java 10.71% <0.00%> (ø)
...java/org/apache/pulsar/broker/rest/TopicsBase.java 0.00% <0.00%> (ø)
...sar/broker/service/plugin/EntryFilterProvider.java 0.00% <0.00%> (ø)
...org/apache/pulsar/broker/web/ExceptionHandler.java 0.00% <0.00%> (ø)
...rg/apache/pulsar/broker/web/PulsarWebResource.java 57.25% <ø> (-0.85%) ⬇️
.../pulsar/client/impl/ControlledClusterFailover.java 64.70% <0.00%> (+2.08%) ⬆️
... and 74 more

@lhotari lhotari changed the title [improve][misc] Use ThreadLocal Jackson ObjectMapper to reduce overhead [improve][misc] Use shared Jackson ObjectMapper to reduce overhead Jan 11, 2023
@lhotari
Copy link
Member Author

lhotari commented Jan 12, 2023

@nicoloboschi PTAL . I have added a ProtectedObjectMapper class which prevents mutating the shared ObjectMapper config.

@lhotari lhotari requested a review from nicoloboschi January 12, 2023 13:05
Copy link
Contributor

@nicoloboschi nicoloboschi left a comment

Choose a reason for hiding this comment

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

LGTM
I like the new pattern 👍

Optional<Long> version) {
try {
byte[] content = ObjectMapperFactory.getThreadLocal().writeValueAsBytes(policies);
byte[] content = ObjectMapperFactory.getMapper().writer().writeValueAsBytes(policies);
Copy link
Contributor

Choose a reason for hiding this comment

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

How about having ObjectMapperFactory.getWriter() and ObjectMapperFactory.getReader() methods ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking of that, but the challenge is that there's also the Yaml versions and the ObjectMapper configured to filter null fields. That would result in a lot of similar methods. It's a tradeoff.
Leaving ObjectMapperFactory as-is and creating a completely new class would be another option. I'd suggest that it's left as another PR to continue refactoring.

@lhotari lhotari requested a review from cbornet January 12, 2023 21:09
…s to empty caches

- this is useful in tests to prevent class / classloader leakages
@lhotari lhotari merged commit ec102fb into apache:master Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs ready-to-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants