JBoss Performance Tuning tips and hints – Part 1

Important notice: This article has been originally written for JBoss EAP 5 and contains some best practices to tune the application server and the environment where it's running. Although some indications are still valid, we recommend also taking a look at the following articles which are more recent:

This is a two part tutorial which contains a large collection of Performance tuning tips for JBoss Application Server.

JBoss tuning tip 1: Tune the garbage collector

One strength of the J2SE platform is that it shields the developer from the complexity of memory allocation. However, once garbage collection is the principal bottleneck, it is worth understanding some aspects of this hidden implementation

An object is considered garbage when it can no longer be reached from any pointer in the running program. The most straightforward garbage collection algorithms simply iterate over every reachable object. Any objects left over are then considered garbage. The time this approach takes is proportional to the number of live objects,
The complete address space reserved for object memory can be divided into the young and tenured generations.

jboss performance tuning tutorial

The young generation consists of eden and two survivor spaces. Most objects are initially allocated in eden. One survivor space is empty at any time, and serves as the destination of any live objects in eden and the other survivor space during the next copying collection. Objects are copied between survivor spaces in this way until they are old enough to be tenured (copied to the tenured generation).

A third generation closely related to the tenured generation is the permanent generation which holds data needed by the virtual machine to describe objects that do not have an equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation
Use the the command line option -verbose:gc causes information about the heap and garbage collection to be printed at each collection. For example, here is output from a large server application:

jboss performance tuning

It’s demonstrated that an application that spends 10% of its time in garbage collection can lose 75% of its throughput when scaled out to 32 processors

JBoss tuning tip 2: Set -Xms and -Xmx to the same value

By default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. Setting -Xms and -Xmx to the same value. This increase predictability by removing the most important sizing decision from the virtual machine.

JBoss tuning tip 3: Use server VM

The server JVM is better suited to longer running applications. To enable it simply set the -server option on the command line.

JBoss tuning tip 4:  Turn off distributed gc

The RMI system provides a reference counting distributed garbage collection algorithm. This system works by having the server keep track of which clients have requested access to remote objects running on the server. When a reference is made, the server marks the object as “dirty” and when a client drops the reference, it is marked as being “clean.”. However this system is quite expensive and by default runs every minute.

Set it to run every 30 minute at least


JBoss tuning tip 6:  Turn on parallel gc

If you have multiple proessors you can do your garbage collection with multiple threads. By default the parallel collector runs a collection thread per processor, that is if you have an 8 processor box then you’ll garbage collect your data with 8 threads. In order to turn on the parallel collector use the flag –XX:+UseParallelGC. You can also specify how many threads you want to dedicate to garbage collection using the flag -XX:ParallelGCThreads=8.

JBoss tuning tip 7: Don’t use Huge heaps, use a cluster

More JVMs/smaller heaps can outperform fewer JVMs/Larger Heaps. So instead of huge heaps, use additional server nodes. Set up a JBoss cluster and balance work between nodes.

JBoss tuning tip 8: Don’t choose an heap larger then 70% of your OS memory

Choose a maximum heap size not more then 70% of the memory to avoid excessive page faults and thrashing.

JBoss tuning tip 9:  Tune the Heap ratio

This is one of most important tuning factor: the heap ratio. The heap ratio specifies how the amount of the total heap will be partitioned between the young and the tenured space.  What happens if you have lots of long lived data (cached data, collections ) ? maybe you’re in this situation:

jboss performance tuning

The problem here is that the long lived data overflows the tenured generation. When a collection is needed the tenured generation is basically full of live data. Much of the young generation is also filled with long lived data. The result was that a minor collection could not be done successfully (there wasn’t enough room in the tenured generation for the anticipated promotions out of the young generation) so a major collection was done.

The major collection worked fine, but the results again was that the tenured generation was full of long lived data and there was long lived data in the young generation. There was also free space in the young generation for more allocations, but the next collection was again destined to be a major collection.
This will eventually bring your application to crawl !!!!!

By decreasing the space in the young generation and putting that space into the tenured generation (a value of NewRatio larger than the default value was chosen), there was enough room in the tenured generation to hold all the long lived data and also space to support minor collections. This particular application used lots of short lived objects so after the fix mostly minor collections were done.

NewRatio is a flag that specifies the amount of the total heap that will be partitioned into the young generation. It’s the tenured-generation-size / young-generation-size. For example, setting -XX:NewRatio=3 means that the ratio between the young and tenured generation is 1:3

If you want a more precise control over the young generation : NewSize is the initial size of the young generation, MaxNewSize will specify the maximum size of the young generation

What is the recommeded heap ratios ? Set the tenured generation to be approximately two times the size of the young generation.
This recommendation is only a starting point, you have to tune from there and to do that you have to gather and analyze the garbage collection statistics.

JBoss tuning tip 10:  Monitor the free memory with monitors and snapshots 

Check out our Monitoring Tips.

JBoss tuning tip 11: Tune the Operating System

Each operating system sets default tuning parameters differently. For Windows platforms, the default settings are usually sufficient. However, the UNIX and Linux operating systems usually need to be tuned appropriately

Linux tuning parameters:

  • Since in Linux everything is a file, check the file-max parameter:
$ cat /proc/sys/fs/file-max
  • Increase the maximum number of file descriptors. You can check the existing configuration using the ulimit -n command:
$ ulimit -n

If your console shows 1024, it is insufficient. Please add the following lines to your /etc/security/limits.conf file and reboot your machine:

root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
  • For high load environments, add the following configuration to your /etc/sysctl.conf file:
net.core.somaxconn = 1024
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
net.ipv4.tcp_rmem = 4096 12582912 16777216
net.ipv4.tcp_max_syn_backlog = 8096
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240 65535

Use sysctl -p command or reboot your node for the changes to take effect.

  • Increase default socket send/receive buffer:
# default socket receive buffer
$ sysctl -w net.core.rmem_default=262144

# default socket send buffer
$ sysctl -w net.core.wmem_default=262144

# max socket receive buffer
$ sysctl -w net.core.rmem_max=262144

# max socket send buffer size
sysctl -w net.core.wmem_max=262144
  • Optimize MTU.

The TCP maximum transfer unit is 1512 on the Internet. If you are sending larger packets it’s a good idea to increase MTU size in order to reduce packet fragmentation (especially if you have a slow network):

$ vi /etc/sysconfig/network-scripts/ifcfg-eth0

– add “MTU=9000” (for gigabit ethernet)
– restart the interface (ifdown eth0;ifup eth0)


Applications using Java native memory (such as java.nio API) may tune application performance and memory use by adjusting the MALLOC_ARENA_MAX environment variable.
Java native memory is managed by the glibc library which uses multiple memory pools that malloc can allocate memory from. Especially for threaded programs, using multiple memory pools can speed up memory allocation (be reducing locking) and improve overall performance.
With some memory allocation patterns, this performance improvement can come at the cost of somewhat greater app memory consumption. This may especially be the case for programs that create and destroy many threads and allocate lots of memory in those threads.
If your application has MALLOC_ARENA_MAX=2 set but has plenty of memory to spare, you may be able to see small gains in response time by increasing this value.

  • Use Big Memory Pages

Default page size is 4KB (usually too small!). Check page size with:

$ cat /proc/meminfo

If you see “HugePage_Total,” “HugePages_Free” and “Hugepagesize”, you can apply this optimization

Here’s how to do it (2GB Heap Size Example):

$ echo 2147483647 > /proc/sys/kernel/shmmax
$ echo 1000 > /proc/sys/vm/nr_hugepages

In Sun’s JVM, add this flag: XX:+UseLargePages

Solaris tuning parameters:

Check the following TCP parameters with your sysadmin:

/dev/tcp tcp_time_wait_interval
/dev/tcp tcp_conn_req_max_q
/dev/tcp tcp_conn_req_max_q0
/dev/tcp tcp_ip_abort_interval
/dev/tcp tcp_keepalive_interval
/dev/tcp tcp_rexmit_interval_initial
/dev/tcp tcp_rexmit_interval_max
/dev/tcp tcp_rexmit_interval_min
/dev/tcp tcp_smallest_anon_port
/dev/tcp tcp_xmit_hiwat
/dev/tcp tcp_recv_hiwat
/dev/ce instance
/dev/ce rx_intr_time

Tip: Use the netstat -s -P tcp command to view all available TCP parameters.

Set TCP-related tuning parameters using the ndd command


$ ndd -set /dev/tcp tcp_conn_req_max_q 1638
  • Tune /etc/system filesystem

Each socket connection to JBoss consumes a file descriptor. To optimize socket performance, you may need to configure your operating system to have the appropriate number of file descriptors.

See Solaris documentation about this parameters:

set rlim_fd_cur
set rlim_fd_max
set tcp:tcp_conn_hash_size (Solaris 8 and 9)
set ip:ipcl_conn_hash_size (Solaris 10)
set shmsys:shminfo_shmmax Note: This should only be set for machines that have at least 4 GB RAM or higher.
set autoup
set tune_t_fsflushr

JBoss tuning tip 12: Lots of Requests ? check JBoss thread pool

JBoss thread pool is defined into conf/jboss-service.xml

 <mbean code="org.jboss.util.threadpool.BasicThreadPool"
 <attribute name="Name">JBoss System Threads</attribute>
 <attribute name="ThreadGroupName">System Threads</attribute>
 <attribute name="KeepAliveTime">60000</attribute>
 <attribute name="MaximumPoolSize">10</attribute>
 <attribute name="MaximumQueueSize">1000</attribute>
 <attribute name="BlockingMode">run</attribute>

For most applications this defaults will just work well, however if you are running an application with issues lots of requests to jboss (such as EJB invocations) then monitor your thread pool. Open the Web Console and look for the MBean jboss.system:service=ThreadPool.

jboss performance tuning

Start a monitor on the QueueSize parameter. Have you got a QueueSize which reaches MaximumPoolSize ? then probably you need to set a higher MaximumPoolSize pool size attribute

Watchout! Speak at first with your sysadmin and ensure that the CPU capacity support the increase in threads.

Watchout! if your threads make use of JDBC connections you’ll probably need to increase also the JDBC connection pool accordingly. Also verify that your HTTP connector is enabled to handle that amount of requests.

JBoss tuning tip 13: Check the Embedded web container

JBoss supports connectors for http, https, and ajp. The configuration file is server.xml and it’s deployed in the root of JBoss web container (In JBoss 4.2.0 it’s:  “JBOSS_HOME\server\default\deploy\jboss-web.deployer”)

 <Connector port="8080" address="${jboss.bind.address}"    
 maxThreads="250" maxHttpHeaderSize="8192"
 emptySessionPath="true" protocol="HTTP/1.1"
 enableLookups="false" redirectPort="8443" acceptCount="100"
 connectionTimeout="20000" disableUploadTimeout="true" />

The underlying HTTP connector of JBoss needs to be fine tuned for production settings.  The important parameters are:

maxThreads – This indicates the maximum number of threads to be allocated for handling client HTTP requests. This figure corresponds to the concurrent users that are going to access the application. Depending on the machine configuration, there is a physical limit beyond which you will need to do clustering.

acceptCount – This is the number of request threads that are put in request queue when all available threads are used. When this exceeds, client machines get a request timeout response.

compression – If you set this attribute to “force”, the content will be compressed by JBoss and will be send to browser. Browser will extract it and display the page on screen. Enabling compression can substantially reduce bandwidth requirements of your application.

So how do you know if it’s necessary to raise your maxThreads number ? again open the web console and look for the MBean jboss.web:name=http-,type=ThreadPool. The key attribute is currentThreadsBusy. If it’s about 70-80% of the the maxThreads you should consider raising the number of maxThreads.

jboss performance tuning

 Watch out! if you increase the maxThreads count you need to raise your JBoss Thread pool accordingly.

JBoss tuning tip 14:  Turn off JSP Compilation in production

JBoss application server regularly checks whether a JSP requires compilation to a servlet before executing a JSP. In a production server, JSP files won’t change and hence you can configure the settings for increased performance.

Open the web.xml in deploy/jboss-web.deployer/conf folder. Look for the jsp servlet in the file and modify the following XML fragment as given below:


Hungry for Tuning?

Speed-up your Enterprise Applications with our WildFly Performance Tuning guide!

Ok. now keep reading…….JBoss performance tuning part 2