-
Notifications
You must be signed in to change notification settings - Fork 543
add singleton implementation of JsonObject to optimize memory usage #2353
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
base: series/0.14.x
Are you sure you want to change the base?
add singleton implementation of JsonObject to optimize memory usage #2353
Conversation
b38e5be
to
aa792ef
Compare
aa792ef
to
2989877
Compare
@jnicoulaud-ledger If you're looking to enhance the performance of parsing and serialization with circe AST even more, I'd like to introduce you to the jsoniter-scala-circe project. This library can significantly reduce latency and boost throughput, especially when using the jsoniter-core API for parsing and serialization from/to byte arrays or java.nio.ByteBuffers. Additionally, it offers improved safety, particularly when handling BigDecimal numbers, as discussed here. Furthermore, the jsoniter-scala-benchmark module can be used to verify that there are no performance regressions in your pull requests. It includes real-world message samples from Google Maps, GitHub Actions, and Twitter APIs, ensuring that your changes maintain optimal performance. |
|
||
fromLinkedHashMap(map) | ||
val fieldsSeq = fields.iterator.toSeq | ||
(fieldsSeq.size: @switch) match { |
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 think you should avoid converting the fields
into a seq, just to use size
, use sizeCompare
or sizeIs
on the Iterable
and determine if its 0 or 1, or greater instead... this way you don't have to materialize the Seq, and sizeCompare
is cheap in comparison.
fromLinkedHashMap(map) | ||
val fieldsSeq = fields.iterator.toSeq | ||
(fieldsSeq.size: @switch) match { | ||
case 0 => empty |
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.
empty
is actually sub-optimial as well, maybe we could create a dedicated empty
type as well instead of it being final val empty: JsonObject = new MapAndVectorJsonObject(Map.empty, Vector.empty)
|
||
private[circe] final def fromMapAndVector(map: Map[String, Json], keys: Vector[String]): JsonObject = | ||
new MapAndVectorJsonObject(map, keys) | ||
(map.size: @switch) match { |
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.
Same critique on size above, use sizeCompare or sizeIs instead so a full traversal isn't used when it isn't needed.
|
||
private[circe] final def fromLinkedHashMap(map: LinkedHashMap[String, Json]): JsonObject = | ||
new LinkedHashMapJsonObject(map) | ||
(map.size: @switch) match { |
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.
Also this.
This pull request optimizes memory usage in the edge case where there are many objects with only one field, default
LinkedHashMap
container has a lot of memory overhead in such cases.Notes: