densh / scala-offheap

Experimental type-safe off-heap memory for Scala.
BSD 3-Clause "New" or "Revised" License
532 stars 38 forks source link

Too high on-heap memory and GC overhead #114

Closed l15k4 closed 7 years ago

l15k4 commented 7 years ago

Hey,

I think that the value classes that hold allocation address put significant on-heap memory and GC overhead :

import scala.offheap
object Play extends App {
  implicit val alloc = offheap.malloc
  val arr = new scala.Array[offheap.Array[Byte]](Int.MaxValue/16)
  var counter = 0
  while (counter < Int.MaxValue/16) {
    arr(counter) = offheap.Array.fromArray("foobar".getBytes)
    counter+=1
  }
}

This ends up with java.lang.OutOfMemoryError: GC overhead limit exceeded even if I use -Xmx4096 even though theoretically it should need only Int.MaxValue/16 * 8 so -Xmx2048m tops

If I measure the resulting Array using SizeEstimator.scala it has 3758MB which is 27B per element, which is a offheap.Array value class that should break down to 8 bytes long only but it obviously doesn't.

It's probably my misuse of scala Value Classes, I think that if I do this scala.Array[offheap.Array[Byte]](x,y,z) then it doesn't matter then offheap.Array is a value class and it breaks down to a normal x, y, z instances on heap which I didn't expect to happen.

$ java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2ubuntu0.16.04.2-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)

And scala version from scala-offheap project

DarkDimius commented 7 years ago

Scala currently stores arrays of value classes in a boxed representation, and, I'd assume, that by the time scala-native comes, there's not much one can do with it.

Dotty had a prototype in works that would support storing arrays of value classes efficiently https://github.com/lampepfl/dotty/pull/1228

l15k4 commented 7 years ago

Good to know, thanks!

@DarkDimius btw can you see a reason why offheap.Array is not Allocatable ? So that one could have offheap array of arrays ? Size is known upfront for memory alignment, so it could be doable, right?

It would help for building other collection types like Map