多核平台下的Java优化
Java 利用多核技术也带来了一些问题,主要是多线程共享内存引起了。目前内存和 CPU 之间的带宽是一个主要瓶颈,每个核可以独享一部分高速缓存,可以提高性能。
1、代码优化
- 线程数要大于等于核数
如果使用多线程,只有运行的线程数比核数大,才有可能榨干 CPU 资源,否则会有若干核闲置。要注意的是,如果线程数目太多,就会占用过多内存,导致性能不升反降。JVM 的垃圾回收也是需要线程的,所以这里的线程数包含 JVM 自己的线程
- 尽量减少共享数据写操作
每个线程有自己的工作内存,在这个区域内,系统可以毫无顾忌的优化,如果去读共享内存区域,性能也不会下降。但是一旦线程想写共享内存(使用 volatile 关键字),就会插入很多内存屏障操作(Memory Barrier 或者 Memory Fence)指令,保证处理器不乱序执行。相比写本地线程自有的变量,性能下降很多。处理方法是尽量减少共享数据,这样也符合”数据耦合”的设计原则。
- 使用 synchronize 关键字
在 Java1.5 中,synchronize 是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用 Java 提供的 Lock 对象,性能更高一些。但是到了 Java1.6,发生了变化。synchronize 在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在 Java1.6 上 synchronize 的性能并不比 Lock 差。官方也表示,他们也更支持 synchronize,在未来的版本中还有优化余地。
- 使用乐观策略
传统的同步并发策略是悲观的。表现语义为:多线程操作一个对象的时候,总觉得会有两个线程在同时操作,所以需要锁起来。乐观策略是,假设平时就一个线程访问,当出现了冲突的时候,再重试。这样更高效一些。Java 的 AtomicInteger 就是使用了这个策略。
- 使用线程本地变量(ThreadLocal)
使用 ThreadLocal 可以生成线程本地对象的副本,不会和其他线程共享。当该线程终止的时候,其本地变量可以全部回收。
- 类中 Field 的排序
可以将一个类会频繁访问到的几个 field 放在一起,这样他们就有更多的可能性被一起加入高速缓存。同时最好把他们放在头部。基本变量和引用变量不要交错排放。
- 批量处理数组
现在处理器可以用一条指令来处理一个数组中的多条记录,例如可以同时向一个 byte 数组中读或者写 store 记录。所以要尽量使用 System.arraycopy ()这样的批量接口,而不是自己操作数组。
2、JVM 优化
- 启用大内存页
现在一个操作系统默认页是4K。如果你的 heap 是4GB,就意味着要执行1024*1024次分配操作。所以最好能把页调大。这个配额设计操作系统,单改 Jvm 是不行的。Linux 上的配置有点复杂,不详述。
在 Java1.6 中 UseLargePages 是默认开启的,LasrgePageSzieInBytes 被设置成了4M。笔者看到一些情况下配置成了128MB,在官方的性能测试中更是配置到256MB。
- 启用压缩指针
Java 的64的性能比32慢,原因是因为其指针由32位扩展到64位,虽然寻址空间从4GB 扩大到 256 TB,但导致性能的下降,并占用了更多的内存。所以对指针进行压缩。压缩后的指针最多支持32GB 内存,并且可以获得32位 JVM 的性能。
在 JDK6 update 23 默认开启了,之前的版本可以使用-XX:+UseCompressedOops 来启动配置。
性能可以看这个评测,性能的提升是很可观。
- 启用 NUMA
numa 是一个 CPU 的特性。SMP 架构下,CPU 的核是对称,但是他们共享一条系统总线。所以 CPU 多了,总线就会成为瓶颈。在 NUMA 架构下,若干 CPU 组成一个组,组之间有点对点的通讯,相互独立。启动它可以提高性能。
NUMA 需要硬件,操作系统,JVM 同时启用,才能启用。Linux 可以用 numactl 来配置 numa,JVM 通过-XX:+UseNUMA 来启用。
- 激进优化特性
在 Java1.6 中,激进优化(AggressiveOpts)是默认开启的。激进优化是一般有一些下一个版本才会发布的优化选项。但是有可能造成不稳定。前段时间以讹传讹的 JDK7的 Bug,就是开启这个选项后测到的。
- 逃逸分析
让一个对象在一个方法内创建后,如果他传递出去,就可以称为方法逃逸;如果传递到别的线程,成为线程逃逸。如果能知道一个对象没有逃逸,就可以把它分配在栈而不是堆上,节约 GC 的时间。同时可以将这个对象拆散,直接使用其成员变量,有利于利用高速缓存。如果一个对象没有线程逃逸,就可以取消其中一切同步操作,很大的提高性能。
但是逃逸分析是很有难度的,因为花了 cpu 去对一个对象去分析,要是他不逃逸,就无法优化,之前的分析血本无归。所以不能使用复杂的算法,同时现在的 JVM 也没有实现栈上分配。所以开启之后,性能也可能下降。
可以使用-XX:+DoEscapeAnalysis 来开启逃逸分析。
- 高吞吐量 GC 配置
对于高吞吐量,在年轻态可以使用 Parallel Scavenge,年老态可以使用 Parallel Old 垃圾收集器。
使用-XX:+UseParallelOldGC 开启,可以将-XX:ParallelGCThreads 根据 CPU 的个数进行调整。可以是 CPU 数的1/2或者5/8。
- 低延迟 GC 配置
对于低延迟的应用,在年轻态可以使用 ParNew,年老态可以使用 CMS 垃圾收集器。
可以使用-XX:+UseConcMarkSweepGC 和-XX:+UseParNewGC 打开。
可以将-XX:ParallelGCThreads 根据 CPU 的个数进行调整。可以是 CPU 数的1/2或者5/8
可以调整-XX:MaxTenuringThreshold (晋升年老代年龄)调高,默认是15.这样可以减少年老代 GC 的压力。
可以-XX:TargetSurvivorRatio,调整 Survivor 的占用比率。默认50%.调高可以提供 Survivor 区的利用率。
可以调整-XX:SurvivorRatio,调整 Eden 和 Survivor 的比重。默认是8。这个比重越小,Survivor 越大,对象可以在年轻态呆更多时间。
原文:http://www.yankay.com
相关推荐
Java程序性能优化是每个开发人员都需要关注的重要领域,它涵盖了多个方面,旨在提高代码执行效率,减少资源消耗,以及提升应用程序的稳定性和响应速度。在本文中,我们将深入探讨Java性能优化的关键点,帮助你的Java...
Java程序性能优化是每个开发人员都需要关注的重要领域,特别是在企业级应用中,高效稳定的Java程序能够显著提升用户体验,降低服务器资源消耗。这本书“Java程序性能优化 让你的Java程序更快、更稳定”提供了深入的...
Java并发编程是一个复杂而重要的主题,特别是在开发大型分布式系统时。Amino框架是Java并发编程的一个工具,旨在简化多线程编程,提高程序的效率和可维护性。本篇文章将深入探讨Amino框架的核心概念、功能以及如何在...
- **并发问题**:由于 `HashMap` 在 JDK 1.7 和 JDK 1.8 中均不支持并发操作,因此在多线程环境下容易出现并发问题,甚至可能导致死锁。为了解决这个问题,可以使用 `ConcurrentHashMap`,它在 `java.util....
这个框架极大地提升了多核处理器环境下Java程序的性能。 JVM7还加强了对动态语言的支持,通过JSR 292( invokespecial 字节码指令的扩展)使得其他非Java语言能在JVM上运行得更加顺畅,为JVM上的语言多元化奠定了...
- **实现方式**:可以通过`volatile`关键字、`synchronized`关键字或`java.util.concurrent`包下的锁机制(如`ReentrantLock`)来实现可见性。 - **例子**:使用`synchronized`关键字同步方法或代码块可以确保同一...
相比于进程,线程具有更轻量级的特性,切换成本更低,因此在多核处理器系统中,多线程可以充分利用硬件资源,提高程序性能。 Java中创建线程有两种主要方式:一是继承`java.lang.Thread`类,二是实现`java.lang....
动态语言支持(invokedynamic)为Java平台引入了更灵活的调用机制,为动态语言如Groovy和JavaScript提供了更好的集成。 此外,JDK 6还包含了丰富的API,如集合框架(List、Set、Map等),IO流,网络编程,多线程,...
Java线程是Java编程语言中用于实现并发处理的关键机制之一。线程是程序执行流的最小单位,它允许一个程序在同一时间执行多个任务,从而提高了程序的效率和资源利用率。在Java中,线程的创建和管理被内置到语言本身,...
《精通Lambda表达式:Java多核编程》这本书深入探讨了Java编程中的一种重要特性——Lambda表达式,以及如何在多核环境下充分利用这一特性提高程序性能。Lambda表达式是Java 8引入的关键特性之一,它极大地简化了函数...
此外,在多核CPU环境下,Query Cache的扩展性较差,因为刷新缓存时需要全局锁定。 2. **Memcached**: - **优点**:提供更高的灵活性和定制能力,可以缓存任何类型的数据结构,支持多种数据序列化方式。 - **缺点...
标题提及了两本书籍资源——"Scala程序设计(第2版).pdf"和"Scala程序设计-JAVA虚拟机多核编程实战.pdf",这表明主题聚焦在Scala编程语言以及其与Java虚拟机(JVM)多核编程的结合应用上。描述简单明了,确认了这两...
- **性能评估**:实验结果显示,在相同的硬件环境下,Java在矩阵相乘任务上的性能优于C#。特别是当矩阵尺寸较大时,Java的优势更为明显。这可能是因为Java的垃圾回收机制以及JIT(Just-In-Time)编译器的优化技术...
它的设计兼顾了面向对象技术基础和跨平台的特性,这得益于其独特的运行时环境——Java虚拟机(JVM)。Java语言以其健壮性、安全性、跨平台性、高性能等特点,得到了业界的广泛认可。 Java语言的执行模式是半编译和...
《Tomcat7.0性能优化——挑战极限精简版》 Tomcat作为一款广泛应用的开源Java Servlet容器,其性能优化是许多开发者关注的重点。本文将深入探讨如何对Tomcat7.0进行性能优化,旨在帮助你挑战其运行效率的极限。 一...
Java 8 Stream API 是一种强大的数据处理工具,它允许开发者以声明式的方式处理集合数据,极大地提高了代码的可读性...记得在实际操作中注意性能优化,合理选择串行流和并行流,以及避免在终端操作中进行不必要的计算。
本书旨在帮助读者掌握Java 9中的并发与并行编程技术,通过丰富的示例和实践案例,让开发者能够更好地利用多核处理器的优势,提高程序性能。 #### 描述:并发编程的基础概念与实践技巧 虽然描述部分简略,并未涉及...
Java 7在功能上进行了多方面的增强和改进,包括性能优化、新的API、安全性和工具集的增强等。对于初学者而言,学习Java 7是进入Java世界的良好起点。 ### 二、Java 7的新特性 #### 1. 垃圾回收器改进 Java 7中的...