Why a sawtooth shaped graph?

15,136

Solution 1

The sawtooth pattern in the heap usage can be explained by the fact that several local variables are created during the invocation of the System.out.println invocation. Most notably in the Oracle/Sun JRE, several HeapCharBuffer instances are created in the young generation, as noted in the following snapshot obtained using the memory profiler of VisualVM:

Visual VM - Memory snapshot

The interesting bit is in the number of live objects that are present on the heap. The sawtooth pattern results from the young-gen garbage collection cycle that occurs when the eden space fills up; since there is no heavy computational activity performed in the program, the JVM is able to execute several iterations of the loop, resulting in the eden space (of 4MB is in size) filling up. The succeeding young-gen collection cycle then clears out most of the garbage; it is almost always the whole of the eden space, unless the objects are still in use, as indicated by the following gc trace obtained from VisualVM:

Visual VM GC probes

The behavior of the sawtooth pattern can thus be explained by a series of object allocations in rapid succession that fill up the eden space, triggering a young gen garbage collection cycle; this process repeats cyclically with no delays as the underlying JVM process is not preempted by another process, and the main thread within the JVM that is responsible for the object allocations is also not preempted by another thread.

Solution 2

Any process allocating objects at regular rate will result in a steady increase in heap memory consumption, followed by instantaneous drops when the garbage collector collects the no longer used objects, resulting in that sawtooth shape.

In case you wonder why your java process keeps allocation memory while writing to System.out, keep in mind that other threads (for instance the one feeding the current memory statistics to JVisualVM) may be the ones allocating the memory.

Solution 3

There's lots of places it could be coming from, and it's likely implementation dependent. At least the following are possible (but are all merely speculation)

  • somewhere in the stack of streams underneath System.out.println there is a byte array allocation (given that one of the basic methods of an output stream is write(bytes []b, int off, int len))

  • it's overhead used by the monitoring software you're using (I've not used it)

  • it's overhead in the netbeans VM where it ends up showing the output

Solution 4

Actually jVisualVM causing additional object allocation. jVisualVM and jconsole are using Java Management Extensions. Attaching to running application and requesting JVM metrics causing that additional objects are being created. You can verify this by adding to your program call to

Runtime.getRuntime().freeMemory() 

which reports free memory in JVM heap. It will show [almost] no memory change by running your code, but as soon as you connect jVisualVM to your program you'll see memory usage increase.

Share:
15,136

Related videos on Youtube

buch11
Author by

buch11

It should be either of them:c.php, java.c , or java.php...

Updated on June 20, 2022

Comments

  • buch11
    buch11 almost 2 years

    When I run the below mentioned code using NetBeans, the allocated heap size graph resembles a sawtooth shape. I am attaching the screen capture from JVisualVM which shows the heap allocation graph in with a sawtooth shape. The program is a simple infinite loop printing "Hello, World!" into the console.

    public class HelloWorld {
        public static void main(String a[]){
            while(true) {
                System.out.println("Hello, World!");
            }
        }
    }
    

    enter image description here Can anyone explain the reason behind the shape of the graph of used heap?

    PS: This happens even if I run it without using NetBeans, so it is most likely not related to NetBeans...

    • Owen
      Owen over 12 years
      And seems to vary by a good... uh... 3 megabytes? Can that really be true?
    • skaffman
      skaffman over 12 years
      You get some insight into this by trying other garbage collector algorithms. See here for info: tikalk.com/java/…
    • SyntaxT3rr0r
      SyntaxT3rr0r over 12 years
      @buch11: never underestimate the gigantic amount of garbage even the most trivial Java method/API is able to generate. I've done multi-threaded scientific computation using Java and I can tell you there are so many gotchas it's not even funny ;) You have to realize most Java programmers will happily use things like Map<Integer,Long> and tell you that if it's not a bottleneck there's nothing wrong with it. Java is basically a world where nearly everybody generates countless waste and think: "The garbage collector will take care of it". There's a reason why Photoshop ain't written in Java ;)
  • Vineet Reynolds
    Vineet Reynolds over 12 years
    You're welcome. Btw, I did not get perfect sawtooth waves, as I kept Alt-tabbing between VisualVM and Eclipse. Your screenshot on the other hand indicates that you've been running VisualVM for quite sometime.
  • buch11
    buch11 over 12 years
    actually i was programming something that makes use of threads,suddenly the code went into infinite loo,i went to JVisualVM to check which of the threads are running/sleeping/waiting.,and the sawtooth came in front of me,at once i thought it was something related to threads,but then tried running the code above and all the puzzles started from there only...so yay my VisualVM was running all the time.
  • Agnius Vasiliauskas
    Agnius Vasiliauskas over 5 years
    Not necessary GC collection of objects will result in instantaneous drops. When objects to be allocated are very big, say one object ~ 10% of RAM size, then we may get reversed sawtooth graph. I.E. object allocator will grab new memory instantly, but GC collector will free memory at steady decrease rate. So actual graph depends on average object size in memory
  • meriton
    meriton over 5 years
    Do you have any evidence for this rather surprising claim?
  • Agnius Vasiliauskas
    Agnius Vasiliauskas over 5 years
    Yes I have - check here. Test code was simple - PHP code in a non-stop loop was generating big new objects ~ object with encapsulated array of 90 million elements
  • meriton
    meriton over 5 years
    PHP? This question is about Java ... AFAIK all Java garbage collectors are compacting, and therefore free memory pretty much instantaneously.
  • Agnius Vasiliauskas
    Agnius Vasiliauskas over 5 years
    Quote If the rate of garbage creation exceeds the rate at which young/nursery generation scavenges can clear objects before they are tenured, then this garbage builds up in the tenured region In my case garbage creation rate is slow, because huge objects are allocated, so probably tenured region is not filled with many objects and thus no sharp drops.
  • Holger
    Holger over 2 years
    Local variables are irrelevant. The garbage collection is about objects, not variables. Further, it’s worth noting that this pattern is not specific to the young generation, but will occur every time you have multiple allocations but a single freeing operation.
  • Holger
    Holger over 2 years
    @AgniusVasiliauskas the garbage collection always produces a vertical line, only its length differs depending on the amount of freed memory. The different angles seen in the tools are just a property of the tools, because they connect points of measuring. So these angles just depend on the polling intervals, either set by the tool author or being a configurable option. Tell the tool to poll more often, and the decay will look sharper.