在Solaris上,64位Java的可扩展性不如32位Java

在Solaris上,64位Java的可扩展性不如32位Java,java,jetty,solaris,load-testing,Java,Jetty,Solaris,Load Testing,各位,上周在一个大客户站点的Java服务器应用程序负载测试研讨会上,当使用64位JVM时,我们只能运行1300-1800个并发会话,而在相同的配置下,我们可以使用32位JVM运行2800个并发会话 环境资料: Solaris 10、Java 1.6.0_30、Jetty 8.1.5、Web应用程序的I/O绑定为每个进程1000个大部分空闲线程,生成了6-12个Java进程,差异不大,出现故障时内存16GB未满,CPU容量不足50%,文件描述符设置为65536 当使用64位JVM运行时,我们达到了

各位,上周在一个大客户站点的Java服务器应用程序负载测试研讨会上,当使用64位JVM时,我们只能运行1300-1800个并发会话,而在相同的配置下,我们可以使用32位JVM运行2800个并发会话

环境资料: Solaris 10、Java 1.6.0_30、Jetty 8.1.5、Web应用程序的I/O绑定为每个进程1000个大部分空闲线程,生成了6-12个Java进程,差异不大,出现故障时内存16GB未满,CPU容量不足50%,文件描述符设置为65536

当使用64位JVM运行时,我们达到了一个状态,CPU不足50%,机器级和Java进程级的大量内存仍然可用。 在这一点上,我们开始在产品的各个层次上获得“IOException”和“eofeexception”。据我们所知,当时没有真正的网络或通信问题。Solaris机器似乎耗尽了与套接字通信相关的资源,64位JVM消耗的资源似乎是32位JVM的两倍

有什么想法吗? 一个显著的区别是64位JVM每个线程堆栈消耗1024k,而32位JVM每个线程仅消耗512k。这可能是原因吗? Solaris上的线程堆栈和套接字I/O是否从同一内存池分配? 这个游泳池可以增加吗?
我们是否应该尝试将64位VM上的线程堆栈大小减少到512k?

原因是堆栈主要包含指针或指针大小的原语。在64位中,它们的大小是32位中的两倍。因此,对于相同的堆栈“深度”,需要加倍字节。1024K相当于您以前的设置。不要更改它。

我建议尝试将
-XX:+UseCompressedOops
选项(压缩普通对象指针)添加到JVM中,并查看测试的比较结果


此选项可能还不是您使用的JVM版本的默认选项,它补偿了64位指针大小的负面影响,同时保持了总体64位虚拟内存空间优势。

我的结论是,我们遇到的限制如下: (1) 服务器处理的总内存分配超过了服务器机器的物理内存大小--> (2) Solaris服务器开始将内存页交换到磁盘--> (3) 由于交换,Java垃圾收集变得非常慢(交换非常糟糕,有时单个收集需要300秒以上!)--> (4) 使用套接字通信时,一些进程正在等待I/O,而另一些进程则陷入垃圾收集--> (5) 由于执行GC的进程不响应来自其他进程的请求,因此在意外的地方会出现套接字超时和EOF异常。 (6) 我们不会出现内存错误,因为从技术上讲,Solaris的交换文件中仍然有可用内存,并且没有超过Java最大堆大小

因此,我的结论如下: (1) 32位JVM比64位JVM扩展得更好的原因是,与32位JVM相比,64位JVM需要50%或更多的内存,因此与32位JVM相比,64位JVM在更小的负载下分配所有可用的物理内存。 (2) 在给定Solaris服务器上运行4000个并发会话的关键是减少内存消耗和/或增加可用物理内存。 (3) 为了更好地扩展,您需要32位JVM能够生成更多线程,默认情况下,每个进程只能生成3000个线程,这对于我的特定用例来说是不够的

配置更改: (1) 添加以下命令行标志以监视垃圾收集-XX:+PrintGCDetails-XX:+PrintGCTimeStamps (2) 将线程堆栈大小减少到-Xss384k这允许每个进程运行更多线程,并减少进程的内存分配。Solaris上32位的默认堆栈大小为512k,64位的默认堆栈大小为1024k。 (3) 使用prstat和vmstat命令监视负载测试期间的内存消耗,并确保没有过度交换。
(4) 不要为每个32位Java进程分配超过-mx800m的内存,以节省内存并加快垃圾收集,如果需要,可以生成更多进程,但请确保不填充物理内存

为了进行公平的比较,我将使用最新版本的Java6IE更新45,因为更新30后出现了许多bug和性能差。理想情况下,您应该使用最新版本的Java 7 update 25操作系统。线程堆栈大小仅使用虚拟内存,即它是最大值,除非实际需要,否则不使用真实内存。我将澄清我的问题,我的下一个64位虚拟机测试应该是什么?我将再次澄清我的问题,我的下一个64位虚拟机测试应该是什么?我的想法是:(1)我们应该升级到Java 1.6.045并安装所有相关的Solaris修补程序,如果这无助于(2)使用-Xss512k减少线程堆栈分配,并使用-XX:+UseCompressedOops标志。我仍然不明白的是,为什么可伸缩性限制会反映为IOException?通常IOException附带消息。你能看到信息是什么吗?顺便说一句,Java 6 update 21的默认设置应该是+UseCompressedOops+