利用虚拟机特性,提高程序性能(方法内联)

Java2与过去的版本相比,性能已有大幅提高,其中包括: 更快的内存分配,更小的类尺寸,垃圾收集性能的改善,还有最新型的监控器和作为标准的内联JIT(Just-In-Time)技术。

在使用Java2虚拟机时,会看到这些性能的改善,然后,如果能够理解速度是怎样提高的,您就能够调整您的应用程序,以充分挖掘每一点性能潜力。

方法内联
新版的JVM可以在运行时 自动内联 简单方法。 在一个未优化的JVM中,每调用一次新的方法,就创建一个新的堆栈框架(stack frame)。 创建一个新的stack frame需要一些额外的资源,其结果是导致系统开销的少许增加。

由于方法内联可在你的程序中减少方法调用的次数,避免了上面谈到的开销,因而可以提高性能。JVM内联代码 内联了 返回常数 或 仅仅访问内部域的方法。为了利用方法内联,可以从一下两件事中选做其一:
(1)使一个方法对JVM所有执行的内联看上去是有吸引力的
(2)在不破坏对象模型的前提下,手工内联一个方法。这里手工内联意味着可以直接从一个方法中将代码移动到正在调用该方法的方法中。

下面的小例子,演示了JVM的自动方法内联:

public class InlineMe {
  int counter = 0;
  public void method1() {
    for (int i=0;i<1000;i++) {
      addCount();
      System.out.println("counter="+counter);
    }
  }

  public int addCount() {
    counter = counter + 1;
    return counter;
  }

  public static void main(String args[]) {
    InlineMe im = new InlineMe();
    im.method1();
  }
}


在当前状态,addCount方法对JVM中内联探测器显得是没有什么吸引力的,因为addCount方法返回一个值。 要发现该方法是否被内联:

java -Xrunhprof:cpu=times InlineMe

它生成一个java.hprof.txt输出文件。类似下面的结果:

CPU TIME (ms) BEGIN (total = 1672) Thu Nov 08 19:37:06 2007
rank   self  accum   count trace method
   1 12.14% 12.14%    2000 300927 sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop
   2  6.58% 18.72%    2000 300953 sun.nio.cs.StreamEncoder.writeBytes
   3  6.52% 25.24%    2000 300931 java.nio.charset.CharsetEncoder.encode
   4  3.71% 28.95%    2000 300950 java.io.BufferedOutputStream.flush
   5  2.87% 31.82%    2000 300934 sun.nio.cs.StreamEncoder.implWrite
   6  2.87% 34.69%    2000 300913 java.nio.HeapCharBuffer.<init>
   7  2.75% 37.44%    2001 300085 java.nio.Buffer.<init>
   8  1.91% 39.35%    1000 300955 sun.nio.cs.StreamEncoder.flushBuffer
   9  1.91% 41.27%    1000 300895 java.lang.StringBuilder.<init>
  10  1.91% 43.18%    2000 300916 java.nio.CharBuffer.hasArray
  11  1.91% 45.10%    1000 300960 java.io.PrintStream.print
  12  1.91% 47.01%    1000 300975 sun.nio.cs.StreamEncoder.flushBuffer
  13  1.91% 48.92%    1000 300978 java.io.OutputStream.flush
  14  1.91% 50.84%    2000 300947 java.io.FileOutputStream.write
  15  1.91% 52.75%    2000 300941 java.nio.Buffer.limit
  16  1.91% 54.67%    2001 300083 java.nio.Buffer.limit
  17  1.91% 56.58%    1000 300935 sun.nio.cs.StreamEncoder.write
  18  1.91% 58.49%   12893 300924 sun.nio.cs.Surrogate.is
  19  1.85% 60.35%    2000 300932 java.nio.charset.CoderResult.isUnderflow
  20  1.85% 62.20%    6000 300923 java.nio.ByteBuffer.arrayOffset
  21  1.85% 64.06%    1000 300954 sun.nio.cs.StreamEncoder.implFlushBuffer
  22  1.85% 65.91%    6000 300919 java.nio.CharBuffer.arrayOffset
  23  1.85% 67.76%    2000 300933 java.nio.Buffer.remaining
  24  1.79% 69.56%    2000 300948 java.io.BufferedOutputStream.flushBuffer
  25  1.79% 71.35%    1000 300980 java.io.PrintStream.newLine
  26  1.79% 73.15%    1000 300971 java.io.OutputStreamWriter.write
  27  0.96% 74.10%   12893 300925 sun.nio.cs.ext.DoubleByteEncoder.encodeSingle
  28  0.96% 75.06%    1000 300959 java.io.PrintStream.write
  29  0.96% 76.02%    2000 300915 java.nio.Buffer.hasRemaining
  30  0.96% 76.97%    2000 300928 sun.nio.cs.ext.DoubleByteEncoder.encodeLoop
  31  0.96% 77.93%    1000 300909 java.io.Writer.write
  32  0.96% 78.89%    1000 300967 java.io.Writer.write
  33  0.96% 79.84%    1000 300894 java.lang.StringBuilder.append
  34  0.96% 80.80%       1 300629 sun.net.www.ParseUtil.decode
35  0.96% 81.76%       1 300982 com.spr.base.InlineMe.method1
  36  0.96% 82.72%       5 300276 java.lang.String.toLowerCase
  37  0.96% 83.67%       5 300260 java.io.Win32FileSystem.normalize
  38  0.96% 84.63%      12 300174 java.net.URL.getRef
  39  0.96% 85.59%    1000 300937 java.io.BufferedWriter.flushBuffer
  40  0.96% 86.54%    1000 300964 java.io.BufferedWriter.min
  41  0.90% 87.44%    1000 300972 java.io.BufferedWriter.flushBuffer
  42  0.90% 88.34%    1000 300966 java.io.BufferedWriter.write
  43  0.90% 89.23%    1000 300961 java.io.PrintStream.ensureOpen
  44  0.90% 90.13%    2000 300952 java.nio.Buffer.clear
  45  0.90% 91.03%    2000 300946 java.io.BufferedOutputStream.write
  46  0.90% 91.93%    2000 300940 java.nio.Buffer.flip
  47  0.90% 92.82%    2000 300917 java.nio.ByteBuffer.hasArray
  48  0.90% 93.72%    2000 300914 java.nio.CharBuffer.wrap
  49  0.90% 94.62%    1000 300908 java.io.BufferedWriter.write
  50  0.90% 95.51%    1000 300893 java.lang.AbstractStringBuilder.append
  51  0.90% 96.41%    1000 300890 java.lang.AbstractStringBuilder.<init>
  52  0.90% 97.31%    1000 300881 com.spr.base.InlineMe.addCount
  53  0.90% 98.21%    1000 300968 java.io.BufferedWriter.newLine
  54  0.90% 99.10%      27 300439 java.lang.String.charAt
  55  0.90% 100.00%       1 300114 java.lang.StringCoding$StringDecoder.decode
CPU TIME (ms) END



如果将addCount方法改造为不再返回一个值,则虚拟机可在运行时将其内联:

public void addCount() {
  counter = counter+1;
}

再次运行profiler
java -Xrunhprof:cpu=times InlineMe
这次,java.hprof.txt的输出应该是不同的。addCount方法已经找不到了,它被内联了!

CPU TIME (ms) BEGIN (total = 1688) Thu Nov 08 19:45:06 2007
rank   self  accum   count trace method
   1 22.33% 22.33%    2000 300927 sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop
   2  6.46% 28.79%   12893 300924 sun.nio.cs.Surrogate.is
   3  4.68% 33.47%    1000 300980 java.io.PrintStream.newLine
   4  4.62% 38.09%    2000 300953 sun.nio.cs.StreamEncoder.writeBytes
   5  2.84% 40.94%    2000 300934 sun.nio.cs.StreamEncoder.implWrite
   6  2.78% 43.72%    2000 300931 java.nio.charset.CharsetEncoder.encode
   7  2.78% 46.50%    1000 300966 java.io.BufferedWriter.write
   8  2.78% 49.29%    1000 300938 sun.nio.cs.StreamEncoder.isOpen
   9  2.73% 52.01%    2000 300928 sun.nio.cs.ext.DoubleByteEncoder.encodeLoop
  10  1.90% 53.91%    2000 300944 java.nio.ByteBuffer.arrayOffset
  11  1.84% 55.75%    2000 300932 java.nio.charset.CoderResult.isUnderflow
  12  1.84% 57.58%    2000 300950 java.io.BufferedOutputStream.flush
  13  1.84% 59.42%    2000 300947 java.io.FileOutputStream.write
  14  1.84% 61.26%    1000 300976 java.io.OutputStreamWriter.flushBuffer
  15  1.84% 63.09%    2000 300941 java.nio.Buffer.limit
  16  1.84% 64.93%    1000 300975 sun.nio.cs.StreamEncoder.flushBuffer
  17  1.84% 66.77%       1 300982 com.spr.base.InlineMe.method1
  18  1.78% 68.54%    1000 300972 java.io.BufferedWriter.flushBuffer
  19  1.78% 70.32%    1000 300935 sun.nio.cs.StreamEncoder.write
  20  0.95% 71.27%    1000 300973 sun.nio.cs.StreamEncoder.isOpen
  21  0.95% 72.22%    1000 300974 sun.nio.cs.StreamEncoder.implFlushBuffer
  22  0.95% 73.16%      16 300238 java.lang.AbstractStringBuilder.expandCapacity
  23  0.95% 74.11%    1000 300960 java.io.PrintStream.print
  24  0.95% 75.06%    1000 300959 java.io.PrintStream.write
  25  0.95% 76.01%    1000 300958 java.lang.String.indexOf
  26  0.95% 76.95%    2000 300949 java.io.OutputStream.flush
  27  0.95% 77.90%       5 300295 sun.misc.URLClassPath$JarLoader.<init>
  28  0.95% 78.85%    2000 300940 java.nio.Buffer.flip
  29  0.95% 79.80%    1000 300937 java.io.BufferedWriter.flushBuffer
  30  0.95% 80.75%    1000 300979 java.io.BufferedOutputStream.flush
  31  0.95% 81.69%    2000 300929 java.nio.charset.CoderResult.isOverflow
  32  0.95% 82.64%    6000 300923 java.nio.ByteBuffer.arrayOffset
  33  0.95% 83.59%    4000 300921 java.nio.Buffer.limit
  34  0.95% 84.54%    2001 300084 java.nio.Buffer.position
  35  0.95% 85.49%    6000 300919 java.nio.CharBuffer.arrayOffset
  36  0.95% 86.43%    2000 300917 java.nio.ByteBuffer.hasArray
  37  0.95% 87.38%       6 300580 java.lang.Integer.parseInt
  38  0.95% 88.33%    1000 300908 java.io.BufferedWriter.write
  39  0.95% 89.28%    1000 300890 java.lang.AbstractStringBuilder.<init>
  40  0.95% 90.23%    1000 300901 java.lang.String.<init>
  41  0.89% 91.11%    1000 300896 java.lang.AbstractStringBuilder.stringSizeOfInt
  42  0.89% 92.00%    1000 300892 java.lang.String.getChars
  43  0.89% 92.89%    1000 300902 java.lang.StringBuilder.toString
  44  0.89% 93.78%       2 300661 java.io.Win32FileSystem.normalize
  45  0.89% 94.67%    2000 300914 java.nio.CharBuffer.wrap
  46  0.89% 95.56%    1000 300978 java.io.OutputStream.flush
  47  0.89% 96.45%       1 300352 sun.net.www.ParseUtil.decode
  48  0.89% 97.33%    2000 300945 java.io.PrintStream.ensureOpen
  49  0.89% 98.22%    1000 300963 java.io.BufferedWriter.ensureOpen
  50  0.89% 99.11%    4000 300920 java.nio.Buffer.position
  51  0.89% 100.00%    2001 300083 java.nio.Buffer.limit
CPU TIME (ms) END

你可能感兴趣的:(java,jvm,虚拟机,ext,sun)