Reputation: 107
Is it possible to calculate memory consumption for each thread? Suppose I divided my task into 4 threads then I want to know how much memory consumption by each threads? I need it to know average and peak memory usage from my threads.
Upvotes: 7
Views: 12903
Reputation: 1255
You could use Native Memory Tracking to get info about the threads in general, but I'm not sure how to get info about each thread individually.
Add -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics
to your vm options when starting your application:
java -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -jar myjar.jar
Now, if you run:
$jps -l
to find the java process on your machine and then
$jcmd <PID> VM.native_memory
you will see something like the following:
Native Memory Tracking:
Total: reserved=2344374KB +4399KB, committed=567362KB +19659KB
...
- Thread (reserved=87894KB, committed=19126KB +756KB)
(thread #159)
(stack: reserved=87132KB, committed=18364KB +756KB)
(malloc=577KB #956)
(arena=184KB #316)
...
With this info you could do 19126KB/159=120KB to get an average committed size of memory for each thread. The problem is this won't tell you each thread individually and some threads will be larger and others smaller.
You can also use:
$jcmd <PID> VM.native_memory baseline
$jcmd <PID> VM.native_memory summary.diff
This would tell you the difference between a baseline instant of time and a run that you could do during peak traffic.
One word of caution: Enabling NMT has some additional overhead associated with it. You may want to weigh the risks of running an application in PROD with that enabled.
Upvotes: 2
Reputation: 340060
As others noted, most objects live on the heap. That heap memory is shared across threads. So there is no way to identify which threads are responsible for the size of the heap.
But threads do get their own chunk of memory: the stack.
As I recall from presentations by Ron Pressler of Oracle in 2020…
Each thread is assigned a certain amount of memory for its stack. Since currently threads in Java implementations based on OpenJDK are mapped one-to-one to host OS’ thread, the stack size is arbitrarily set to something like a meg. More memory may be allocated if needed, but is not reduced.
The plot thickens with virtual threads (fibers) proposed in Project Loom.
Project Loom adds new capabilities to the Java concurrency facilities. As part of this, virtual threads are mapped many-to-one to host OS threads (a.k.a. platform/kernel threads). The JVM will manage these virtual threads rather than the OS, “parking” a virtual thread when its code blocks to allow time for another virtual thread to run via execution time assigned to the “real” platform/kernel thread. The scheduling of that “real” platform/kernel thread to actually get work done on the CPU core is controlled by the host OS, with or without Project Loom (at least in Java implementations based on OpenJDK).
➥ As part of this JVM-management of virtual threads, each virtual thread's stack will start out much smaller. And each stack will grow, and shrink(!), as needed.
Because of this efficient use of both CPU and memory, virtual threads are dramatically "cheaper". So we can run more of them. Even millions of virtual threads are possible on common hardware.
Upvotes: 7
Reputation: 1535
Summing up my comment, threads use shared memory. Hence no thread owns any data of it's own apart from the reserved stack memory (which is set during jvm startup).
Since you are focussing on the exact heap size a thread consumes whilst running your jvm, you can simply rather use a memory profiler like visualvm to look at the classes & Objects which your thread creates and assume the consumption size.
You can also ThreadLocal variables to define Objects belonging to a specific thread. This can also help you get the exact memory consumption on a per thread basis.
You can also look at ThreadMXBean, however this is no longer available in the latest jvms.
Upvotes: 2