1

Possible Duplicate:
In Java, what is the best way to determine the size of an object?

I found this piece of code on the net:

static Runtime runtime = Runtime.getRuntime();
...
long start, end;
Object obj;
runtime.gc();
start = runtime.freememory();
obj = new Object(); // Or whatever you want to look at
end =  runtime.freememory();
System.out.println("That took " + (start-end) + " 
bytes.");

But it is not very reliable, any idea on how to do it better?

Community
  • 1
  • 1
Chucky
  • 73
  • 3
  • You can serialize the object and look at how much data was saved. Obviously this will be different from the in-memory object size! – Guillaume Dec 01 '12 at 12:19
  • 4
    *"any idea on how to do it better?"* Any good reason to do it at all? – Andrew Thompson Dec 01 '12 at 12:19
  • See http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object for a more reliable method. – pd40 Dec 01 '12 at 12:22
  • kindly explain in your question what do you want to do with this code – Naeem Ul Wahhab Dec 01 '12 at 12:39
  • Wow, so many critics...THe code is only used to understand what happens inside the VM, and is not part of any production or project code. – Chucky Dec 01 '12 at 12:59

2 Answers2

2

The JVM allocates memory in chunks so it can be performed across threads concurrently. This called the Thread-Local Allocation Buffer.

TLAB - Thread-local allocation buffer. Used to allocate heap space quickly without synchronization. Compiled code has a "fast path" of a few instructions which tries to bump a high-water mark in the current thread's TLAB, successfully allocating an object if the bumped mark falls before a TLAB-specific limit address.

If you turn this off with -XX:-UseTLAB you will get more accurate memory usage information.

public static void main(String... args) {
    for (int i = 0; i < 10; i++) {
        long used1 = memoryUsed();
        new Object();
        long used2 = memoryUsed();
        System.out.println(used2 - used1);
    }
}

public static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

prints with default options

0 0 0 0 0 0 0 0 0 0

with -XX:-UseTLAB

16 16 16 16 16 16 16 16 16 16

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

I have a bit of experience measuring object size and one thing I have learned is to not trust the profiler. It doesn't give real measured values, but guestimates. To make this very specific, it misjudged the size of a reference array by 100% on a 64-bit VM: where the real size is 32 bits per slot, it guessed 64 bits.

Your way of measuring is actually quite OK as long as you are very careful to get familiar with it on your specific configuration and ensure you are getting consistent results. Some additional advice:

  1. never measure the size of a single object, but of an array of a thousand, or a million of objects. This is important to give more realistic results in case of data sharing between objects (a quite typical scenario). Change array sizes to see that the results per object are always the same;

  2. do two or three System.gc()s before and after allocating the array, pausing between them for half a second or so;

  3. don't just measure freeMemory because the heap can grow; measure totalMemory() - freeMemory().

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • When speaking about trusting, `System.gc()` is definitely the one that I don't have trust in :) – Miljen Mikic Dec 01 '12 at 13:10
  • @MiljenMikic You speak from actual experience with this kind of microbenchmarking? I have never had any nondeterminism coming from `System.gc()` I varies across implementations, but is perfectly stable and predictable within a set environment. – Marko Topolnik Dec 01 '12 at 13:13
  • Not with this kind of benchmarking, but generally in other applications. I've tried in two projects to rely on `System.gc()`, but gave up after tracking the memory consumption - it really had "mind of its own". It was Sun JDK Java 1.6.0_xx implementation. – Miljen Mikic Dec 01 '12 at 13:23
  • 1
    Yes, `System.gc()` is not a tool to solve memory problems in a live production app. – Marko Topolnik Dec 01 '12 at 13:30