-
Notifications
You must be signed in to change notification settings - Fork 32
Performance improvements for JacksonConfigParser #218
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
Conversation
Pull Request Test Coverage Report for Build 684
💛 - Coveralls |
This addresses some poor use of Jackson when deserializing JSON to `ProjectConfig` object and improves parse performance by about 15x-40x based on some benchmarks. The custom deserializers were creating new `ObjectMapper` instances on each `deserialize()` invocation. Very wasteful. Eliminates several cases of unecessary round trips of reading JSON string to JSON tree, then back to JSON string to parse a child node. We can eliminate the `GroupJacksonDeserializer` completly and rely on standard Jackson databind annotations. Deserialize Audience conditions using `JsonNode` interface to eliminate intermediate mapping to `List` and `Map`. Adds `JacksonConfigParserBenchmark` (fixes Gradle JMH setup). Benchmark results: Before: Benchmark Mode Cnt Score Error Units JacksonConfigParserBenchmark.parseV2 avgt 40 1668.109 ± 178.586 us/op JacksonConfigParserBenchmark.parseV3 avgt 40 1574.464 ± 25.816 us/op JacksonConfigParserBenchmark.parseV4 avgt 40 2166.621 ± 91.664 us/op After: Benchmark Mode Cnt Score Error Units JacksonConfigParserBenchmark.parseV2 avgt 40 41.292 ± 1.219 us/op JacksonConfigParserBenchmark.parseV3 avgt 40 54.360 ± 0.790 us/op JacksonConfigParserBenchmark.parseV4 avgt 40 128.589 ± 3.728 us/op
6d08b4e
to
fbdf1b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for doing this! Especially for adding the benchmark test for showing the results of the improvement =)
Looks good to me. Just sending back so we can remove those two deserializer classes and update the license headers in the files.
@Override | ||
public ProjectConfig deserialize(JsonParser parser, DeserializationContext context) throws IOException { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
SimpleModule module = new SimpleModule(); | ||
module.addDeserializer(Audience.class, new AudienceJacksonDeserializer()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! Looks like we won't be needing these two classes anymore. Do you mind removing them as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are still being used -- I moved these into a a proper Module
class of their own. See ProjectConfigModule
. We can definitely get rid of them with a little more work, but tried to keep the moving parts to a minimum and focus on perf in this PR.
@@ -0,0 +1,9 @@ | |||
# EditorConfig is awesome: http://EditorConfig.org |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty cool! Will start using it in our projects :)
@@ -0,0 +1,44 @@ | |||
package com.optimizely.ab.config.parser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the license header to this file. You only need to include the year 2018 because it was created this year.
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import com.fasterxml.jackson.annotation.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the license year to 2016-2018
for this and all the files you touched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great improvement!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the copyright headers for files changed in this PR and merged in latest changes from master. @mikeng13 could you take another look?
@Override | ||
public ProjectConfig deserialize(JsonParser parser, DeserializationContext context) throws IOException { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
SimpleModule module = new SimpleModule(); | ||
module.addDeserializer(Audience.class, new AudienceJacksonDeserializer()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are still being used -- I moved these into a a proper Module
class of their own. See ProjectConfigModule
. We can definitely get rid of them with a little more work, but tried to keep the moving parts to a minimum and focus on perf in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
build |
@loganlinn looks like there are some lint errors from the Travis build:
|
@mikeng13 all fixed up |
Thanks! I looked at the Travis builds and they are passing now. HOwever they aren't reporting back to Github. I will merge anyway since all required tests pass. Thanks again for the contribution! |
This addresses some poor use of Jackson when deserializing JSON to
ProjectConfig
object and improves parse performance by about 15x-40xbased on some benchmarks.
The custom deserializers were creating new
ObjectMapper
instances oneach
deserialize()
invocation. Very wasteful.Eliminates several cases of unecessary round trips of reading JSON
string to JSON tree, then back to JSON string to parse a child node.
We can eliminate the
GroupJacksonDeserializer
completly and rely onstandard Jackson databind annotations.
Deserialize Audience conditions using
JsonNode
interface to eliminateintermediate mapping to
List
andMap
.Adds
JacksonConfigParserBenchmark
(fixes Gradle JMH setup).Benchmark results:
Before:
After: