Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

determine size of object: best way to use instrumentation in scala/sbt

According to this question, the standard way to determine the memory size of an object in Java is by using java.lang.instrumentation. After to some research, it looks like there is no Scala specific way to achieve this, so the Java approach should also applies here.

Unfortunately, for a Scala programmer without Java background it is not fully straightforward to adapt this technique in Scala. My questions are:

Question 1

What exactly is happening here? I guess the reason why we have to put a class like ObjectSizeFetcher in a separate JAR is to ensure that it is somehow loaded before the actual program where we want to use it. I assume it is not possible to use instrumentation without the Premain-Class entry and the parameter -javaagent:TheJarContainingObjectFetcher.jar?

Question 2

Is there a simple way to implement the complete work flow in SBT? Currently I only see a somewhat cumbersome solution: I first have to set up a secondary SBT project where I define ObjectSizeFetcher and package it into a JAR. So far I did not figure out how to automatically add the Premain-Class entry to the JAR during packaging, so I would have to solve that manually. Than I can add the resulting JAR to the local libraries of the project where I want to use getObjectSize. For this project I now have to enable fork in run and use javaOptions in run += "-javaagent:TheJarContainingObjectFetcher.jar". Is there a more simple (and less intrusive) work flow to quickly use instrumentation within an existing SBT project? Maybe I can tell SBT directly about a Premain-Class to make this secondary JAR unnecessary?

Question 3

Would you recommend a completely different way to evaluate the memory usage of an object in Scala?

like image 495
bluenote10 Avatar asked Nov 30 '12 13:11

bluenote10


2 Answers

Answer 1: Yes, if you want iinstrumentation, you need to get an instance. You probably can't get it without Premain-Class and -javaagent.

Answer 2: You can (and may need to) use classloaders and create a very simple bootstrap project (in Java or in Scala with Proguard). There are two reasons:

The first reason: conveniency. You may use java.net.URLClassLoader to include standard Scala library and the classes directory of your project. You will not need to repackage it in JAR any more when testing.

The second reason: preventing JAR hell. You probably know that Scala is not binary compatible. You should also know that the Java agent is loaded with the application in the same classloader. If the classloader includes Scala library, application can't simply use another Scala version.

However, if the Java agent doesn't use directly Scala library (e.g. it is a bootstrap application and loads the real agent and its libraries in another classloader), the instrumented application is free to use any Scala library.

Answer 3: I would probably use instrumentation, too.

like image 99
v6ak Avatar answered Oct 13 '22 10:10

v6ak


Answer 3: you can have a look to ktoso/sbt-jol which displays the JOL (Java Object Layout), ie the analysis of object layout schemes in JVMs

// project/plugins.sbt
 addSbtPlugin("pl.project13.sbt" % "sbt-jol" % pluginVersionHere)

It does include the size:

> jol:internals example.Entry

...
[info] example.Entry object internals:
[info]  OFFSET  SIZE   TYPE DESCRIPTION                    VALUE
[info]       0    12        (object header)                N/A
[info]      12     4    int Entry.value                    N/A
[info]      16     4 String Entry.key                      N/A
[info]      20     4        (loss due to the next object alignment)
[info] Instance size: 24 bytes
[info] Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
like image 26
VonC Avatar answered Oct 13 '22 10:10

VonC