2

I need some input on how to best tweak my memory settings to allow a higher number of threads.

I read through the posing on How many threads can a Java VM support? and followed the java example there (dieLikeaDog) and it does work, spawning just under 800 threads before dying.

As in the (dieLikeaDog example) link above, the code makes all the threads it can, until the following error results: java.lang.OutOfMemoryError: unable to create new native thread

Specifying Xss on the command line (e.g. java -Xss104k dieLikeADog) does not change the number of threads created.

I also tried changing -Xms and -Xmx and neither changed the number of threads it could produce.

The one thing that did change the number of threads is my -u ulimit (for max user processes). Making this larger did increase the number of threads.

my ulimits are as follows:

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 46588
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

I am a bit confused as I thought from reading other examples that specifying a smaller -Xss should increase the number of threads.

Is there something else going on that is stopping Xss from working?

In case it matters, I am running on a 64bit fedora 15 system (with 6 gigs of ram):

  OS:
    Linux
    2.6.42.12-1.fc15.x86_64
    amd64

  JVM:
    Sun Microsystems Inc.
    Java(TM) SE Runtime Environment
    Java HotSpot(TM) 64-Bit Server VM
    1.6.0_27
Community
  • 1
  • 1
Andy Dingfelder
  • 2,090
  • 2
  • 18
  • 30
  • What is the reason for dying? Maybe just not enough memory? Try increase -Xmx – Alexei Kaigorodov Nov 28 '12 at 02:13
  • 1
    Good question. As I said above, I tried changing -Xms and -Xmx and neither changed the number of threads it could produce. regarding what message you get, as in the (dieLikeaDog example) link above, the code makes all the threads it can, until the following error results: java.lang.OutOfMemoryError: unable to create new native thread – Andy Dingfelder Nov 28 '12 at 03:44
  • Looks like it is something (not threads) who eats all the memory. To make sure, try -Xms do decrease stack memory for a thread. Try memory profiling tools to find out the hog. – Alexei Kaigorodov Nov 28 '12 at 04:27
  • I had 600m free memory when it stopped. When we ran this on a similar machine with 16 gigs of memory, it stopped at the same number of threads, so IMO it is not free memory, but a system setting or vm issue. As I noted above, we did try increasing and decreasing -Xms and it had no effect. – Andy Dingfelder Nov 28 '12 at 20:02

2 Answers2

3

The -Xss parameter controls how mush memory is allocated for each thread's stack. Choosing a value is a case of balancing stack depth against available memory. Setting a value of -Xss104k means 104KB of your available memory (set with -Xmx ) will be consumed for the stack of each thread started. If you start with -Xmx1024k then memory will be exhausted before you ever reach 10 threads as that 1M of memory includes heap and classes (permgen) as well as thread stacks.

My approach is to first examine the code to run in the thread. Recursive heavy code needs more stack. Code that just iterates over a large set of data probably needs very little stack.

An empirical way to balance the forces involved, is decrease -Xss until you get a StackOverflowError. That means you thread is running out of stack. Add some padding to the last value that worked. If the last value that didn't cause a StackOverflowError was '-Xss1k, the try-Xss2kor-Xss3k. If the stack is wiping out at something like10kI'd try just bumping to15k`.

Now you have a size for the thread stacks. Your total memory (-Xmx) minus permgen, minus the amount of heap required gives you what is left for threads. If you need 1000K for heap and 50K for permgen, and you figured a stack size of 2K, then to run ten threads you're looking at -Xmx1070K as your minimum memory.

That said, take a look at what you're trying to accomplish. Why do you need more threads? Maybe the answer is not more threads, but a different algorithm that can process the data faster while using less threads.

Update

I've struck out portions of my original answer that I have found to be incorrect.

The stack space is not taken from the heap space, they are allocated separately. Both the thread stacks and the heap count toward the process's virtual memory. Reducing the heap allows for more threads and increasing it allows for less.

On a 32-bit JVM, I was able to reduce the stack size to 1K. On a 64-bit JVM, 104K is the minimum.

I did some testing on a 64-bit Windows 7 box with 4G ram and 2 cores.

With a 32-bit JVM, -Xss8k, and -Xmx128m the program gives me ~5000 threads. That seems to be the best case. I did not find a combination of options that would increase the number of threads beyond that point. If I increased the heap size, the max threads droped off. The thread stack size seems like it may be tied to system page size as max threads actually gets worse if I choose less than 8k stacks.

The ~5000 thread limit appears to hold for a 32-bit JVM on Ubuntu Quantal as well.

With a 64-bit JVM, it's a whole different story. With -Xss104k and -Xmx128m the program exceeded 50000 threads. At that point Windows got really unhappy. It stopped responding for several minutes, then started killing other processes. I'm guessing in an attempt to free more memory.

Update:

More testing on Ubuntu: I discovered I had a ulimit set for virtual memory. After ulimit -v unlimited The program tops out ~36000 threads.

Devon_C_Miller
  • 16,248
  • 3
  • 45
  • 71
  • We cannot easily just use less threads, as a there are lots of different apps run in our program that use camel and jms (which create threads for listeners etc.) – Andy Dingfelder Nov 28 '12 at 19:58
  • re using a smaller Xss size, should I be able to use a small size such as 64k? If I try java -Xss64k dieLikeADog, I get: The stack size specified is too small, Specify at least 104k Could not create the Java virtual machine. – Andy Dingfelder Nov 28 '12 at 19:59
  • Im glad to hear you confirm that 104 is the low limit, as that is what I found as well. What I am confused about is why running the following 4 commands all make the same number of threads for me (749): java dieLikeADog java -Xss104k dieLikeADog java -Xmx128m dieLikeADog java -Xss104k -Xmx128m dieLikeADog – Andy Dingfelder Nov 30 '12 at 00:33
0

The reason probably lies within the ulimits you gave:

max user processes              (-u) 1024

Each thread will count against this value. An since you're not only running the JVM quite a lot of threads will already be deducted from that value.

Try executing

ulimit -u 4000

and rerun the tests (within a shell that you executed the command in!), the number of threads you can create should not have increased.

rli
  • 1,745
  • 1
  • 14
  • 25