Is Play JSON smart enough to pre-allocate an IndexedSeq when given a JsArray?

I use Format on my case classes to convert to/from JSON. When dealing with an array of something in the JSON, I’ve always used Seq[...] in the case-class. Due to a performance issue in an unrelated part of my code, I find myself needing to switch from Seq, which gives you a List by default, to IndexedSeq (which gives a Vector) - I am handing off objects with a large sequence (tens of thousands of elements) to a Java library which calls size() repeatedly (Java collections have an O(1) size()… whereas Scala collections like List actually behave like they’re supposed to and have an O(n) size()). My question is - when converting a given JsArray into a case class which has an IndexedSeq, will the converter be smart enough to pre-allocate the IndexedSeq to the length of the elements in the JsArray?

case class Foo(things: Seq[Bar])

object Foo {
  implicit val format = Json.format[Foo]

Anyone? Thanks.

No, it’s not needed. Vector is a tree structure, it’s not just an array like ArrayList. It doesn’t need to be preallocated.

play-json uses a Scala collection builder to build sequences (this is a mutable, high performance structure that allows operations like map to be implemented generically for all collections, each collection provides their own builder). Builders have a sizeHint method to allow builders that can optimise for that to do so, this would allow for preallocation for builders that can do preallocation, but the builder for vector ignores the sizeHint call, it doesn’t need it, vector uses a tree of blocks that it allocates as it needs them, when a block is full, it allocates a new one, adds it to its tree, and starts writing to that, no buffer copies are needed.

That said, I just made this PR so that Play’s traversable reads does set the size hint, this won’t help for Vector, but could help for other seq implementations: