-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
ObjectMapper
default heap consumption increased significantly from 2.13.x to 2.14.0
#3665
Comments
From my understanding, ObjectMapper's should be singleton's as much as possible, So this would be a bad implementation of using the ObjectMapper We use native imaging throughout and don't experience anything like this when it's used properly |
I created 100 ObjectMappers to show the extent of this problem. As you'll see in https://github.com/mhalbritter/graalvm-jackson, it is even observable with only 1 ObjectMapper. 2.14.0 uses ~880x more heap for an empty ObjectMapper compared to 2.13.4.2. Spring Boot in my WebMVC sample app uses 4 of them. Not sure if we can get this down to 1. |
Hmmm - @cowtowncoder this one needs your eyes |
I agree with @mhalbritter, it looks like the heap allocation regression in 2.14 is pretty huge and I hope that something could be refined on Jackson side. @cowtowncoder Looking forward to your feedback, we still have the opportunity to update Jackson before Spring Boot 3 GA is released (expected next week). |
Uh. I did have some concerns about apparent complexity of the improved cache choice, relative to benefits. The baseline for cache should be solid from what I recall, but @pjfanning worked on it most closely. This is unfortunate of course. But just to make sure: that's about 0.5 MB per Given timing I suspect the only potentially easyish win would be changing initial size? And even that would require 2.14.1 release. |
ObjectMapper
default heap consumption increased significantly from 2.13.x to 2.14.0
Ok, looks like there are just 4 cache instances by default (plus one optional):
Initial sizes of all these seem to be between 16 and 65, nothing drastic unless I am missing something. It would be good to get more numbers, if possible, on sizes of individual |
Sorry, I haven’t looked at that caching logic for about 7 years (or 12 when written). At the time the emphasis was concurrency for server-class usages, when a concurrent lru algorithm was a novel, hard problem. I’m sure those AtomicReferences could be replaced by aAtomicReferenceArray to slim it down. It is striped lanes to reduce thread contention, but you could greatly simplify that by knowing what is actually needed here, e.g. a single array is probably fine. I later rewrote this to dynamically stripe light weight, mpsc ring buffers. That is more memory conscious by being slimmer and demand based. |
That sounds useful @ben-manes thank you for sharing. I wonder how easy it'd be to measure -- of course it's not rocket science to just count fields and do it manually but there are probably tools to automate using introspection to at least give static minimums or such. |
I used openjdk’s object layout on the current code to verify padding rules for protecting against false sharing. And for a rough footprint estimate, jamm is good enough for seeing if things line up to expectations. All are just best guesses due to jvm internal complexity, JEP-8249196. |
VisualVM tells me that 1 ObjectMapper on the JVM uses 132.352 B of heap. This is a VisualVM tells me that 1 ObjectMapper in a native image uses 311.944 B of heap. However all LRUmap instances are 507.320 B of heap. Here are all the LRUmap instances on the JVM with the fields which have a reference on them: |
They are all the same size, because the static final int NCPU = Runtime.getRuntime().availableProcessors(); // 9 on my machine
static final int NUMBER_OF_READ_BUFFERS = ceilingNextPowerOfTwo(NCPU); // 16 on my machine
static final int READ_BUFFER_THRESHOLD = 32;
static final int READ_BUFFER_DRAIN_THRESHOLD = 2 * READ_BUFFER_THRESHOLD; // 64
static final int READ_BUFFER_SIZE = 2 * READ_BUFFER_DRAIN_THRESHOLD; // 128
readBuffers = new AtomicReference[NUMBER_OF_READ_BUFFERS][READ_BUFFER_SIZE]; which will make this is a |
Yes, concurrency is unrelated to a maximum cache size. At that time a synchronized lru was standard and perfectly fine in most cases due to single core machines still being common. Those who used this concurrent cache (ConcurrentLinkedHashMap) were servers that had clear needs (4-1024 cores). This led to porting into Guava (CacheBuilder) where we defaulted to 4 for Google’s needs, with a setting to adjust manually (concurrencyLevel). For a more general, modern cache (Caffeine) it now dynamically adjusts the size by need so that low concurrency has a low footprint while high concurrency benefits by trading some extra space. However CLHM is simpler to fork and embed, so decisions that aged poorly are copied over. For Jackson a modest size is enough, thanks to lossy buffers and modest needs, so slimming this down should be simple and effective. Or if you prefer the advanced solution, copying that code and making the minor replacement edits. |
The jackson-databind use case is to actually implement LRU behavior and not clear the whole cache when it fills (unlike 2.13-and-before implementation). The use of PrivateMaxEntriesMap (a renamed fork of https://github.com/ben-manes/concurrentlinkedhashmap) is to be able to cap the entry size of the map and to evict the LRU instances when the entry size limit is reached. We could certainly try to reduce the |
I've locally switched Right now Spring's implementation is not the dominator here, but we might still revisit the read buffer sizes or how its implementation works. |
@pjfanning (I reworded your desc a bit) -- +1 for capping size of those arrays so that no matter how many cores it would not increase linearly. @bclozel Use of Ultimately I think memory usage per cache should be significant lower than initial implementation. Load testing would be nice, but it is worth noting we didn't perf test new implementation vs old implementation either... |
This is due to cpu cache line sharing which causes coherency bottlenecks as a distinct fields within a block are invalidated together. As the thread distribution is not perfect some shared producers will select the same lane. In a perfect world each slot would be fully padded so that once an index is acquired the two producers do not impact each other. That of course is very wasteful (64-byte blocks). The use of object references was a middle ground for partial padding. In these guava benchmarks from one of my attempts to revisit using ring buffers (uses CLQ as quick-and-dirty first pass), the read throughput ranged from 240M (64b) / 256M (256b) / 285M (1kb) ops/s. While the 45M spread sounds scary, in practice the cache reads won't be a bottleneck if it can support ~60M ops/s due to real application work so further gains won't impact system performance.
Please see this jmh benchmark as a reference. |
|
@pjfanning you forgot to account for the # Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# WARNING | Compressed references base/shifts are guessed by the experiment!
# WARNING | Therefore, computed addresses are just guesses, and ARE NOT RELIABLE.
# WARNING | Make sure to attach Serviceability Agent to get the reliable addresses.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
... (many variations) ...
***** Hotspot Layout Simulation (JDK 15, 64-bit model, compressed class pointers, 16-byte aligned)
java.util.concurrent.atomic.AtomicReference object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) N/A
8 4 (object header: class) N/A
12 4 (alignment/padding gap)
16 8 java.lang.Object AtomicReference.value N/A
24 8 (object alignment gap)
Instance size: 32 bytes
Space losses: 4 bytes internal + 8 bytes external = 12 bytes total |
300 kB sounds in the ballpark that was observed.
I wonder how much we could cut things here -- to me some added overhead is fine; |
i dont think it has to be a 2-dimensional array either, could save some space by flattening it. |
@yawkat Going to |
To be fair, since Jackson's caches are likely tiny a Clock (aka Second Chance) policy would be adequate if you wanted a much simpler rewrite. That was my original stop-gap when starting to explore a general approach. It is simply a FIFO with a mark bit that is set on a read and reset during an O(n) eviction scan. That has similar hit rates to an LRU with lock-free reads, but writes block on a shared lock and large caches have GC-like pauses due to scanning. For a small cache like I imagine these to be, anything simple (even just FIFO or random) is likely good enough. I think it would be perfectly fine to write a very simple, fast, low overhead cache that is specific to your needs. |
I have bit ambivalent feelings about this. On one hand, yes, use case specific would be good. On the other hand, using something (as close to) off-the-shelf (as possible) is great. |
Ok at this point I am optimistic about being able to optimize I wonder if use of |
@cowtowncoder I tried to add exactly such a test (though the limit is fairly lax), but ran into these issues with JOL on CI: #3675 (comment) |
Fixed for 2.14.1. |
Awesome, thanks a lot for this quick update! Looking forward to leverage Jackson |
Nice, thanks a lot! |
I'll see if I could find time today to release a patch version; cannot promise it but will try my best. |
Ta-dah! I did it. 2.14.1 release mostly done, last couple of artifacts on their way to Maven Central (Scala module may take bit longer). Please LMK if you find issues. |
Fix an important memory consumption regression, see FasterXML/jackson-databind#3665 for more details. Closes spring-projectsgh-29539
### What changes were proposed in this pull request? This pr aims upgrade `Jackson` related dependencies to 2.14.1 ### Why are the changes needed? This version include an optimization of heap memory usage for Jackson 2.14.x: - FasterXML/jackson-databind#3665 The full release notes as follows: - https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Pass GitHub Actions Closes #38771 from LuciferYang/SPARK-41239. Authored-by: yangjie01 <yangjie01@baidu.com> Signed-off-by: Sean Owen <srowen@gmail.com>
@yawkat |
@cowtowncoder ugh, or just disable it for now. ive given up on making the results resilient to gc, there is too much going on, weird caches with soft references and such. maybe it will be less flaky with epsilon gc, but that's not available on java 8 so i didn't try it for the ci |
Prior to this commit, the `ConcurrentLruCache` implementation would use arrays of `AtomicReference` as operation buffers, and the buffer count would be calculated with the nearest power of two for the CPU count. This can result in significant heap memory usage as each `AtomicReference` buffer entry adds to the memory pressure. As seen in FasterXML/jackson-databind#3665, this can add a significant overhead for no real added benefit for the current use case. This commit changes the current implementation to use `AtomicReferenceArray` as buffers and reduce the number of buffers. JMH benchmarks results are within the error margin so we can assume that this does not change the performance characteristics for the typical use case in Spring Framework. Fixes gh-29520
### What changes were proposed in this pull request? This pr aims upgrade `Jackson` related dependencies to 2.14.1 ### Why are the changes needed? This version include an optimization of heap memory usage for Jackson 2.14.x: - FasterXML/jackson-databind#3665 The full release notes as follows: - https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Pass GitHub Actions Closes apache#38771 from LuciferYang/SPARK-41239. Authored-by: yangjie01 <yangjie01@baidu.com> Signed-off-by: Sean Owen <srowen@gmail.com>
### What changes were proposed in this pull request? This pr aims upgrade `Jackson` related dependencies to 2.14.1 ### Why are the changes needed? This version include an optimization of heap memory usage for Jackson 2.14.x: - FasterXML/jackson-databind#3665 The full release notes as follows: - https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.14.1 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Pass GitHub Actions Closes apache#38771 from LuciferYang/SPARK-41239. Authored-by: yangjie01 <yangjie01@baidu.com> Signed-off-by: Sean Owen <srowen@gmail.com>
* Upgrade to Reactor 2020.0.25 See spring-projectsgh-29464 * Polish AOT ref docs * Update testing chapter regarding Servlet 6.0 baseline for mocks * Document TestSocketUtils in the testing chapter * Fix Javadoc formatting issue in TestSocketUtils * Revert "Ignore HttpComponents Javadoc" This reverts commit f50b472. HttpComponents Javadoc is available again. See spring-projectsgh-29479 See https://issues.apache.org/jira/browse/HTTPCLIENT-2227 * Fix section formatting in the testing chapter * Document AOT support in the TestContext framework Closes spring-projectsgh-29482 * Assert fixed in DefaultErrorResponseBuilder Fixed assert on wrong constructor fields * Polish * Align javadoc of DefaultParameterNameDiscoverer with its behavior * Polishing deprecated methods Added since and forRemoval to Deprecated methods. * Add milestone repo for optional Netty 5 support Closes spring-projectsgh-29498 * Next development version (v6.0.1-SNAPSHOT) * Suppress "removal" warnings in CronSequenceGeneratorTests * Polishing * Fix Javadoc formatting issues for headings Headings in method-level Javadoc must be h4 or higher in recent versions of Java. * Update Jackson-based decoders to reflect 2.14 baseline See spring-projectsgh-29508 * Refactor Asciidoctor attributes in reference docs This commit reorganizes the asciidoctor attributes for the reference documentation. Instead of being contributed partially by the build and individual documents, attributes are now shared in common files that are included in top sections. * Polishing * Add callouts to Kotlin examples for parity * Add missing callouts * Work around code example callout bug This commit adds callouts to two sets of Java/Kotlin code examples in the @ModelAttribute section for Web MVC in order to work around the "Code example has callout from a different code example" bug. This also aligns the Web MVC examples with the WebFlux examples. As a side note, the bug can also be seen in the WebFlux documentation if the callouts are removed from the first Java/Kotlin examples in the @ModelAttribute section for WebFlux. Thus it appears to be a general issue related to examples within a given section of the documentation when some examples have callouts and others do not, likely due to a bug in the Javascript that provides this feature. See spring-projectsgh-29505 * Polishing * Generalize Jackson version numbers This commit removes specific version info from Jackson codecs and converters, in favor of generic info or removing the version information all together. See spring-projectsgh-29508 * Use lambda expression for Callable example in ref docs * Document GraalVM substitutions upcoming removal * Update documentation to mention Java 17+ baseline Closes spring-projectsgh-29514 * Fix link to WebFlux section Closes spring-projectsgh-29513 * Set error status in Observation Servlet filter Prior to this commit, the Observation Servlet filter would record unhandled exceptions on the observation context but would leave the default HTTP response status as is. Servlet containers do set the response status in that case to 500 by default. Not doing that at the Servlet filter level results in invalid observations, stating that the HTTP response status is 200 (because the error status hasn't been set yet by the container) and as a result, the outcome is SUCCESS. This commit ensures that the error status is set in those cases, aligning the behavior with Servlet containers. Fixes spring-projectsgh-29512 * Polish AbstractAutowireCapableBeanFactory and use instanceof pattern matching Closes spring-projectsgh-29499 * Polish contribution * Polishing * Polish asciidoc attributes * Reorganize and modularize the Testing chapter in the reference manual Closes spring-projectsgh-29522 * Document RuntimeHints testing strategies Closes spring-projectsgh-29523 * Disable checkstyle for reference docs code snippets * Fix broken link to Web MVC Testing section * Remove TODOs in WebFlux ref docs * Polishing * Fix link to WebFlux section in reference manual Closes spring-projectsgh-29525 * Introduce appendix in Testing chapter in the reference manual This commit moves the Annotations and Further Resources sections to the new Appendix. See spring-projectsgh-29522 * Reinstate `chapter` asciidoc attribute for Web MVC * Polish asciidoc attributes * Ensure source code in framework-docs is compiled in the build This also ensures that the source code can be properly imported into an IDE. * Polish ref docs - stop referring to Java Config as new - stop referring to Struts 2.x as if it were new - polish AOT documentation - etc. * Polish ref docs * Ensure code listing callouts are displayed incorrectly in core-beans.adoc Closes spring-projectsgh-29457 * Fix a syntax error in an XML listing by adding a missing double-quote Closes spring-projectsgh-29456 * Update LogAdapter to allow build-time code removal Allow for example to remove those classes and 90 related methods when Logback is used: - org.apache.commons.logging.LogAdapter$JavaUtilAdapter - org.apache.commons.logging.LogAdapter$JavaUtilLog - org.apache.commons.logging.LogAdapter$LocationResolvingLogRecord - org.apache.commons.logging.LogAdapter$Log4jAdapter - org.apache.commons.logging.LogAdapter$Log4jLog - org.apache.commons.logging.LogAdapter$LogApi - org.apache.logging.log4j.message.ObjectMessage - org.apache.logging.log4j.message.ReusableObjectMessage - org.apache.logging.log4j.simple.SimpleLoggerContext - org.apache.logging.log4j.simple.SimpleLoggerContextFactory Closes spring-projectsgh-29506 * Do not use LocalVariableTableParameterNameDiscoverer in AOT mode Closes spring-projectsgh-29531 * Revert "Ensure source code in framework-docs is compiled in the build" This reverts commit c45f8b7. * Make GeneratorStrategy.generate unreachable on native This change provides also more information to the user about the missing generated class when that happens. Closes spring-projectsgh-29521 * Apply 'instanceof pattern matching' in spring-web Closes spring-projectsgh-29530 * Polish contribution See spring-projectsgh-29530 * Apply additional 'instanceof pattern matching' in spring-web See spring-projectsgh-29530 * Use Set.of() for constant sets where appropriate * Fix link to Bean Utils Light Library in BeanUtils Javadoc The URL for the BULL library has changed (not sure when, probably way back). This updates it to the correct location. Closes spring-projectsgh-29534 * Make SourceHttpMessageConverter optional As a follow-up to spring-projectsgh-29277, and since the JAXB support is now triggered by the classpath presence of a JAXB implementation, it makes sense to make SourceHttpMessageConverter, previously configured unconditionally, optional. That makes a big difference on native (1M of RSS reduction with current typical Spring Boot 3 arrangement, 3.4M when other usages of XML are not reachable). It also brings more consistency between Spring MVC and Spring WebFlux, and means that XML support for Spring web applications now needs to be enabled explicitly. As a consequence, Spring web applications using javax.xml.transform.Source now needs to configure SourceHttpMessageConverter explicitly in RestTemplate or Spring MVC. Closes spring-projectsgh-29535 * Upgrade to Jackson 2.14.1 Fix an important memory consumption regression, see FasterXML/jackson-databind#3665 for more details. Closes spring-projectsgh-29539 * Fix some typos in Kotlin WebClient example code Closes spring-projectsgh-29538 * Upgrade to Kotlin 1.7.21 Closes spring-projectsgh-29543 * Refine LogAdapter#isPresent Align LogAdapter#isPresent with ClassUtils#isPresent in order to catch NoClassDefFoundError and other errors. Closes spring-projectsgh-29506 * Fix Javadoc link text in BindingResult Closes spring-projectsgh-29551 * Polishing * Polish ServletWebRequest and DefaultServerWebExchange - The return values of ServletWebRequest.validateIfUnmodifiedSince and DefaultServerWebExchange.validateIfUnmodifiedSince are not used. So I think that it is better to remove the return statements. - Add missing @nullable declarations to eTag method parameters. - Simplify if statements Closes spring-projectsgh-29460 * Polish contribution See spring-projectsgh-29460 * Apply 'instanceof pattern matching' * Exclude LocalVariableTableParameterNameDiscoverer based on native image check See spring-projectsgh-29531 * Apply 'instanceof pattern matching' * Polishing * Use AssertJ's hasSize() for collections and maps Achieved via a global search-and-replace. * User AssertJ's hasSize() for arrays Achieved via global search-and-replace. * Use AssertJ's isEmpty() instead of hasSize(0) Achieved via global search-and-replace. * Temporarily re-enable ReactorNetty2StompBrokerRelayIntegrationTests To see if it still fails on the CI server as it doesn't fail locally for me, and if it does to get details to investigate. See spring-projectsgh-29287 * Deprecate LocalVariableTableParameterNameDiscoverer completely LocalVariableTableParameterNameDiscoverer is not registered by default anymore now. Java sources should be compiled with `-parameters` instead (available since Java 8). Also retaining standard Java parameter names for all of Spring's Kotlin sources now. Closes spring-projectsgh-29531 * Add since attribute to Deprecated annotation Also retaining standard Java parameter names for Spring's AspectJ sources now. See spring-projectsgh-29531 * Increase logging for spring-messaging tests See spring-projectsgh-29287 * Fix javadoc link in AOP extensibility documentation Closes spring-projectsgh-29554 * Retain default LocalVariableTableParameterNameDiscoverer with warn log entries For a transition period, LocalVariableTableParameterNameDiscoverer logs a warning for each successful resolution attempt now, suggesting that -parameters was missed. See spring-projectsgh-29531 See spring-projectsgh-29559 * Next development version (v6.0.2-SNAPSHOT) * Log connection info in StompBrokerRelayMessageHandler See spring-projectsgh-29287 * Document removal of CommonsMultipartResolver in MVC setup documentation Closes spring-projectsgh-29562 * Reduce deprecation warn logging to one entry per introspected class Closes spring-projectsgh-29563 * Rely on standard parameter name resolution in Bean Validation 3.0 Just configuring additional Kotlin reflection if Kotlin is present. Closes spring-projectsgh-29566 * ResponseStatusException sets detail from reason again Closes spring-projectsgh-29567 * Additional documentation notes on Java/Kotlin parameter name retention See spring-projectsgh-29563 * Next development version (v6.0.3-SNAPSHOT) * Early support for Jetty 12 (developed against 12.0.0.alpha2) Reflective getHeaders calls to be revisited; see GitHub issue spring-projects#8938 in Jetty project. HttpOutput optimization commented out still in order to avoid alpha build dependency. See spring-projectsgh-29575 * Deprecate JettyWebSocketClient in favor of StandardWebSocketClient JettyWebSocketClient only supported on Jetty 11, to be phased out. Closes spring-projectsgh-29576 * Consistent documentation references to Jakarta WebSocket (2.1) Closes spring-projectsgh-29581 * Reinstate checkstyle for reference docs code snippets This commit also ensures that checks are performed before the application is rendered to get early feedback on errors. * Fix unrendered titles in websocket section This commit fixes the rendering of titles in the websocket section of the reference documentation. Fixes spring-projectsgh-29569 * Split integration chapter in smaller documents This commit splits the integration chapter of the reference documentation in smaller documents for easier maintenance. * Document Observability support in reference docs Closes spring-projectsgh-29524 * Upgrade to Gradle 7.6 Closes spring-projectsgh-29583 * Upgrade Gradle wrapper See spring-projectsgh-29583 * Consistently register CGLIB hints for lazy resolution proxy classes Core JDK/CGLIB proxy registration code extracted to ClassHintUtils. Closes spring-projectsgh-29584 * Remove erroneous Javadoc link * Improve logging in TestContextManager * Forbid loading of test ApplicationContext in AOT mode if AOT processing failed Prior to this commit, if AOT processing of a test's ApplicationContext failed, the TestContext Framework (TCF) still attempted to load the context via standard (JVM) mechanisms when running in AOT mode. For example, if a test class uses Spring Boot's @MockBean, AOT processing of that test's context will fail with a WARN log message, and there will no mapping from that test class to an AOT-generated ApplicationContextInitializer (ACI). Consequently, when the test suite is run in AOT mode that particular test class will currently fail with a confusing stack trace due to the fact that Spring Boot's SpringApplication attempts to locate a "main" ACI instead of the missing "test" ACI (missing because it was not generated during AOT processing). In general, the TCF should not attempt to load an ApplicationContext in "JVM mode" while running in "AOT mode". This commit therefore reworks the logic in DefaultCacheAwareContextLoaderDelegate to fail fast (with a meaningful error message) if an AOT-generated ACI cannot be found while running in AOT mode. This avoids the aforementioned confusion when @MockBean tests fail in AOT mode (on the JVM or within a native image), and it also helps to diagnose build problems if AOT processing has not yet been performed for the project's test suite. Closes spring-projectsgh-29579 * Polish TestContextManager internals * Use JUnit Jupiter annotations as examples in TestContextManager JavaDoc * Update Javadoc regarding JUnit versions * Add MessageSource getters See spring-projectsgh-29574 * Polish Testing chapter * Fix errors in Testing chapter - group code example callouts to ensure callouts are displayed for the correct examples - add missing callouts - fix syntax, annotation attribute names, etc. * Fix typo in observability documentation Closes spring-projectsgh-29590 * Add title to SockJS iFrames for accessibility compliance Closes spring-projectsgh-29594 * Polish contribution See spring-projectsgh-29594 * Polishing * Fix broken tests in SockJsServiceTests See spring-projectsgh-29594 * Avoid deprecation warnings in tests * Rename to AbstractReactiveWebSocketIntegrationTests to avoid duplicate class names * Polishing * Polishing * Add "missing" callout for parity * Fix code example callouts in reference manual * Add missing callout * Apply project formatting rules for ternary operator Discovered via RegEx: ^\s+\? * Apply "instanceof pattern matching" * Introduce update_copyright_headers.sh shell script In order to automate maintenance of copyright headers in our source code (especially when merging PRs from external contributors), this commit introduces an update_copyright_headers.sh script (tested on mac OS) that will update the copyright headers of all Java, Kotlin, and Groovy source files that have been added or modified this year (or at least as far back as the git log history supports it). For example, running this script currently outputs the following. Updating copyright headers in Java, Kotlin, and Groovy source code for year 2022 warning: log for 'main' only goes back to Tue, 16 Aug 2022 16:24:55 +0200 * Update copyright headers for source code changed since August 2022 The changes in this commit were performed using the newly introduced update_copyright_headers.sh script. * Update Javadoc for MBeanTestUtils * Apply update_copyright_headers.sh to staged files as well * Avoid unnecessary parameter name inspection for constructor-arg resolution Closes spring-projectsgh-29612 * Add equals/hashCode methods to ProblemDetail Closes spring-projectsgh-29606 * Polishing * Polish Closes spring-projectsgh-29619 * Use resolved factory method return type for supplier code generation Closes spring-projectsgh-29598 * Polishing * Revised support for Jetty 12 (tested against 12.0.0.alpha2) Avoids HttpFields optimization completely, relying on Servlet header access instead. ServletServerHttpResponse provides applyHeaders/adaptHeaders split for better reuse. See spring-projectsgh-29575 * ResponseStatusException delegates to protected constructor This ensures that by default the reason is used to set the "detail" field. It's a follow-up fix to a27f2e9 which resolved the issue partially. Closes spring-projectsgh-29608 * Deprecate GraphQL media type in favor of new one This commit deprecates the `"application/graphql+json"` media type in favor of the new `"application/graphql-response+json"`, since the former has been removed in graphql/graphql-over-http#215. Closes spring-projectsgh-29617 * Fix URI override for HttpExchange Closes spring-projectsgh-29624 * Upgrade to Apache HttpClient 5.2 Includes JRuby 9.4, Groovy 4.0.6, Hibernate ORM 5.6.14, HSQLDB 2.7.1, SLF4J 2.0.5, Caffeine 3.1.2, Gson 2.10, POI 5.2.3, Protobuf 3.21.10, WebJars Locator 0.52, HtmlUnit 2.67, Mockito 4.9, Checkstyle 10.5 Closes spring-projectsgh-29627 * Fix ErrorResponse#type documentation Closes spring-projectsgh-29632 * Apply "instanceof pattern matching" * Polish Javadoc for ErrorResponse etc. * Reinstate test for JmxUtils.locateMBeanServer() * Update copyright headers * Polish overview for consistency * Do not refer to HTML ref docs from HTML ref docs * Revise PDF ref docs to include TOC, authors, and legal sections * Polish ref docs build * Upgrade JMH build plugins This commit upgrades the Gradle JMH plugin to 0.6.8 and the companion JMH version to 1.36. * Reduce heap memory usage in ConcurrentLruCache Prior to this commit, the `ConcurrentLruCache` implementation would use arrays of `AtomicReference` as operation buffers, and the buffer count would be calculated with the nearest power of two for the CPU count. This can result in significant heap memory usage as each `AtomicReference` buffer entry adds to the memory pressure. As seen in FasterXML/jackson-databind#3665, this can add a significant overhead for no real added benefit for the current use case. This commit changes the current implementation to use `AtomicReferenceArray` as buffers and reduce the number of buffers. JMH benchmarks results are within the error margin so we can assume that this does not change the performance characteristics for the typical use case in Spring Framework. Fixes spring-projectsgh-29520 * Improve invalid Content-Type handling in WebFlux Closes spring-projectsgh-29565 * Simplify form data handling in HttpRequestValues Closes spring-projectsgh-29615 * Improve Netty code sample See spring-projectsgh-29622 * Polishing contribution Closes spring-projectsgh-29622 * Fix canWrite of PartHttpMessageWriter See spring-projectsgh-29631 * Push canWrite down into MultipartHttpMessageWriter The implementation in the base class only matches the MultipartHttpMessageWriter subclass. The other two override it anyway. Closes spring-projectsgh-29631 * Polishing, suppression of deprecation warnings, copyright headers, etc. * Enable backport bot for pull requests * Correct event name in backport bot config * Add write permission in backport bot config * Correct permissions key in backport bot config * Correct (again) permissions key in backport bot config * Fall back to JdkClientHttpConnector as ClientHttpConnector * Fix issue with getHeaders in NoHandlerFoundException Closes spring-projectsgh-29626 * Add convenience methods for binding error messages Closes spring-projectsgh-29574 * Apply "instanceof pattern matching" in spring-webflux Closes spring-projectsgh-29635 * Polishing * Rename MultipartWebClientIntegrationTests classes to avoid duplicate names * Polishing * Reintroduce component index support for Jakarta annotations Spring Framework 6.0 GA introduced a regression in the component index support for Jakarta annotations such as @nAmed and @ManagedBean. Prior to this commit, @nAmed and @ManagedBean components were registered in the component index at build time; however, component scanning failed to find those component at run time. This commit updates ClassPathScanningCandidateComponentProvider so that `jakarta.*` annotation types are once again supported for component scanning via the component index at run time. Closes spring-projectsgh-29641 * Polish var-args declarations Closes spring-projectsgh-29640 * Fix InputStream violation in DataBufferInputStream This commit fixes an issue in DataBufferInputStream::mark, which before did not follow the contract defined by InputStream. Closes spring-projectsgh-29642 * Fix BindingReflectionHintsRegistrar anonymous classes support This commit ensures that giving an anonymous class for reflection hints registration does not result in a NullPointerException, since the canonical name of anonymous classes is null. Fixes spring-projectsgh-29657 * Update copyright headers * Improve Javadoc for SqlLobValue * Introduce @suite classes for individual modules * Polishing * Fix SpEL support for quotes within String literals Prior to this commit, there were two bugs in the support for quotes within String literals in SpEL expressions. - Two double quotes ("") or two single quotes ('') were always replaced with one double quote or one single quote, respectively, regardless of which quote character was used to enclose the original String literal. This resulted in the loss of one of the double quotes when the String literal was enclosed in single quotes, and vice versa. For example, 'x "" y' became 'x " y'. - A single quote which was properly escaped in a String literal enclosed within single quotes was not escaped in the AST string representation of the expression. For example, 'x '' y' became 'x ' y'. This commit fixes both of these related issues in StringLiteral and overhauls the structure of ParsingTests. Closes spring-projectsgh-29604, spring-projectsgh-28356 * Apply 'instanceof pattern matching' in spring-jdbc * Apply 'instanceof pattern matching' in spring-expression * Polishing * Support arrays in AST string representations of SpEL expressions Prior to this commit, SpEL's ConstructorReference did not provide support for arrays when generating a string representation of the internal AST. For example, 'new String[3]' was represented as 'new String()' instead of 'new String[3]'. This commit introduces support for standard array construction and array construction with initializers in ConstructorReference's toStringAST() implementation. Closes spring-projectsgh-29665 * Polishing - primarily automated "clean up" using Eclipse IDE * Polish CGLIB fork - primarily automated "clean up" using Eclipse IDE * Remove top-level permissions from backport-bot.yml * Optimize object creation PartialMatchHelper See spring-projectsgh-29634 * Polishing contribution Closes spring-projectsgh-29634 * Restore top-level read permission for backport bot * Apply 'instanceof pattern matching' in spring-test and Servlet mocks * Polish tests in spring-test * Use URI#create instead of URI constructor where feasible in spring-test * Use URI#create instead of URI constructor where feasible in spring-web * Use URI#create instead of URI constructor where feasible in spring-webflux * Use URI#create instead of URI constructor where feasible in spring-webmvc * Use URI#create instead of URI constructor where feasible in spring-websocket * Introduce additional constructors in MockClientHttp[Request|Response] This commit introduces additional constructors in MockClientHttpRequest and MockClientHttpResponse that were previously only present in the internal "test fixtures" in spring-web. This commit also aligns the mocks in spring-test with the test fixtures in spring-web to simplify continued maintenance of the mocks and test fixtures. Closes spring-projectsgh-29670 * Remove dead code in MockClientHttpRequest * Support properties on records in BindingReflectionHintsRegistrar Closes spring-projectsgh-29571 * Refine BindingReflectionHintsRegistrar Kotlin support Closes spring-projectsgh-29593 * Make @ModelAttribute and @InitBinder reflective Closes spring-projectsgh-29572 * Upgrade to Micrometer 1.10.2 Closes spring-projectsgh-29678 * Start building against Reactor 2022.0.1 See spring-projectsgh-29679 * Upgrade optional dependencies * Use consistent visibility for ResponseEntityExceptionHandler.getMessageSource() See spring-projectsgh-29574 Closes spring-projectsgh-29676 * Clean up Javadoc and source code regarding " ." typos * Align multipart codecs on client and server This commit ensures that the same multipart codecs are registered on both client and server. Previously, only the client enabled only sending multipart, and the server only receiving. Closes spring-projectsgh-29630 * Detect SQL state 23505/40001 as DuplicateKeyException/CannotAcquireLockException Favors PessimisticLockingFailureException over plain ConcurrencyFailureException. Deprecates CannotSerializeTransactionException and DeadlockLoserDataAccessException. Closes spring-projectsgh-29511 Closes spring-projectsgh-29675 * Avoid NPE on BeanDescriptor access with SimpleBeanInfoFactory Closes spring-projectsgh-29681 * Polishing * Polish Javadoc * Update copyright date * Add missing Javadoc See spring-projectsgh-29574 * Revise RepeatableContainersTests * Support repeatable annotation containers with multiple attributes Prior to this commit, there was a bug in the implementation of StandardRepeatableContainers.computeRepeatedAnnotationsMethod() which has existed since Spring Framework 5.2 (when StandardRepeatableContainers was introduced). Specifically, StandardRepeatableContainers ignored any repeatable container annotation if it declared attributes other than `value()`. However, Java permits any number of attributes in a repeatable container annotation. In addition, the changes made in conjunction with spring-projectsgh-20279 made the bug in StandardRepeatableContainers apparent when using the getMergedRepeatableAnnotations() or findMergedRepeatableAnnotations() method in AnnotatedElementUtils, resulting in regressions for the behavior of those two methods. This commit fixes the regressions and bug by altering the logic in StandardRepeatableContainers.computeRepeatedAnnotationsMethod() so that it explicitly looks for the `value()` method and ignores any other methods declared in a repeatable container annotation candidate. Closes spring-projectsgh-29685 * Remove obsolete AttributeMethods.hasOnlyValueAttribute() method See spring-projectsgh-29685 * Upgrade to Reactor 2022.0.1 Closes spring-projectsgh-29679 * Support non-standard HTTP methods in FrameworkServlet This commit ensures that HTTP methods not supported by HttpServlet, for instance WebDAV methods, are still supported in FrameworkServlet. Closes spring-projectsgh-29689 * Remove duplicated test code * Improve Javadoc for RepeatableContainers * Next development version (v6.0.4-SNAPSHOT) * Fix manipulating property sources example in Javadoc for ConfigurableEnvironment The "manipulating property sources" example in the Javadoc for `ConfigurableEnvironment` states that `MutablePropertySources` expect a `Map<String,String>`; whereas it expects a `Map<String,Object>`. Closes spring-projectsgh-29693 * Polishing * Polishing * Improve documentation for literals in SpEL expressions Closes spring-projectsgh-29700 * Extract ResourceEntityResolver HTTPS schema resolution fallback This commit extracts the DTD/XSD remote lookup fallback from the resolveEntity() method into a protected method. A WARN-level logging statement is added to the extracted fallback in order to make it clear that remote lookup happened. Overriding the protected method would allow users to avoid this fallback entirely if it isn't desirable, without the need to duplicate the local resolution code. Closes spring-projectsgh-29697 * Polish contribution See spring-projectsgh-29697 * Fix typos in reference manual Closes spring-projectsgh-29694 * Fix link to Jakarta Mail Closes spring-projectsgh-29694 * Remove ref to JOTM, inactive since 2009 Closes spring-projectsgh-29694 * Remove statement that users could be on Java < 5 Closes spring-projectsgh-29694 * Rework linking to Spring MVC Async support vs WebFlux section The link was previously named "Compared to WebFlux", which is easy to mix up with the various links to equivalent sections in the WebFlux chapter. Here the links point to a small section comparing the Servlet Async API to the WebFlux stack from a high perspective. In this commit we eliminate most of these links, except at the beginning of the Asynchronous section. We also add a small mention of the Servlet configuration in the comparison paragraphs, since the Configuring section is the one furthest from the comparison paragraphs that used to have a link to it. Closes spring-projectsgh-29694 * Fix subsection style in WebFlux Concurrency Model The block title style previously used was not rendered in HTML and the title couldn't be differentiated from the text. Though, it was in the PDF, as italics. Introducing delimited blocks in the open (`--`) style did introduce styling, but the vertical alignment isn't great. This commit turns these block titles to actual (deep) section titles. In the final HTML, at this depth there is no numbering but bold styling is there. The PDF rendering has also been verified to have relevant style. Closes spring-projectsgh-29694 * Change plain 'WebFlux' links to 'See equivalent in the Reactive stack' Closes spring-projectsgh-29694 * Change plain 'WebMVC' links to 'See equivalent in the Servlet stack' Closes spring-projectsgh-29694 * Cross reference WebTestClient section * Update Jakarta Mail info in ref docs Closes spring-projectsgh-29707 * Remove duplicate words in reference manual Found using regular expression: \b(\w+)\s+\1\b * Remove duplicated words in Javadoc * Fix typos in reference manual * Fix formatting in examples * Fix typos in anchors * Polishing * Update copyright headers * Apply "instanceof pattern matching" (spring-projects#29710) * Polishing * Update Trigger & TriggerContext reference documentation Closes spring-projectsgh-29702 * Revert incorrect change to ParamAware Javadoc * Apply "instanceof pattern matching" in spring-aop * Fix path within mapping when pattern contains ".*" Prior to this commit, extracting the path within handler mapping would result in "" if the matching path element would be a Regex and contain ".*". This could cause issues with resource handling if the handler mapping pattern was similar to `"/folder/file.*.extension"`. This commit introduces a new `isLiteral()` method in the `PathElement` abstract class that expresses whether the path element can be compared as a String for path matching or if it requires a more elaborate matching process. Using this method for extracting the path within handler mapping avoids relying on wildcard count or other properties. Fixes spring-projectsgh-29712 * Apply update_copyright_headers.sh Co-authored-by: Juergen Hoeller <hoellerj@vmware.com> Co-authored-by: Sam Brannen <sam@sambrannen.com> Co-authored-by: Andriy <ophiuhus@ukr.net> Co-authored-by: Stephane Nicoll <snicoll@vmware.com> Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com> Co-authored-by: Arjen Poutsma <poutsmaa@vmware.com> Co-authored-by: Spring Builds <spring-builds@users.noreply.github.com> Co-authored-by: Brian Clozel <bclozel@vmware.com> Co-authored-by: Sébastien Deleuze <sdeleuze@vmware.com> Co-authored-by: wizard <925553434@qq.com> Co-authored-by: divcon <sungjinpark.08@gmail.com> Co-authored-by: David Costanzo <david_costanzo@yahoo.com> Co-authored-by: Marten Deinum <mdeinum@gmail.com> Co-authored-by: André Gasser <andre.gasser@protonmail.com> Co-authored-by: jiangying <krivergo3@gmail.com> Co-authored-by: rstoyanchev <rstoyanchev@vmware.com> Co-authored-by: Yanming Zhou <zhouyanming@gmail.com> Co-authored-by: Aashay Chapatwala <49100046+Aashay-Chapatwala@users.noreply.github.com> Co-authored-by: Johnny Lim <izeye@naver.com> Co-authored-by: Baljit Singh <baljit.singh@verizon.com> Co-authored-by: Spark61 <ytspark61@gmail.com> Co-authored-by: CoderYellow <Pf19890604@> Co-authored-by: Moritz Halbritter <mkammerer@vmware.com> Co-authored-by: divcon <sungjin.park08@gmail.com> Co-authored-by: Sam Brannen <sbrannen@vmware.com> Co-authored-by: ShenFeng312 <49786112+ShenFeng312@users.noreply.github.com> Co-authored-by: koo.taejin <koo.taejin@toss.im> Co-authored-by: Carlos Belizón <carlos.belizon.ibanez@gmail.com> Co-authored-by: Simon Baslé <sbasle@vmware.com> Co-authored-by: diguage <leejun119@gmail.com>
Hello,
I'm currently looking at heap consumption when using native image with a Spring Boot 3 application. Spring Boot 3.0 SNAPSHOT uses Jackson 2.14.0-rc3. I noticed that with the upgrade from 2.13.4.2 to 2.14.0 the application uses more heap memory, which i tracked down to this PR. It changed the cache implementation from
ConcurrentHashMap
toPrivateMaxEntriesMap
, which in turn preallocates a lot ofAtomicReference
(they appear to be all empty).I created a reproducer here - it creates an empty objectmapper and then dumps the heap. It has more information and screenshots in the README.
When using Jackson 2.13.4.2 it uses 567 B for the LRUmap, with Jackson 2.14.0 it uses 507320 B for the LRU map. The bad thing is that most of these caches are per
ObjectMapper
- create more of them and it uses even more heap.As we're trying to optimize the memory consumption of native image applications, this is quite a bummer and we hope you can help us out here.
Thanks!
The text was updated successfully, but these errors were encountered: