簡體   English   中英

RandomAccessFile writeInt(int i)vs write(byte [] b)-性能

[英]RandomAccessFile writeInt(int i) vs write(byte[] b) - performance

今天,我對RandomAccessFile遇到了一件有趣的事情。

我注意到,使用RandomAccessFilewriteInt(int i)方法要比使用RandomAccessFilewrite(byte[] b)慢得多,在這里我首先將int值轉換為byte [4]數組。

我正在使用此代碼進行轉換

private static byte[] intToByte(int i)
{
   byte[] result = new byte[4];

   result[0] = (byte) (i >> 24);
   result[1] = (byte) (i >> 16);
   result[2] = (byte) (i >> 8);
   result[3] = (byte) (i);

  return result;
}

區別非常明顯,有利於write(byte[] b)

使用JDK 8在筆記本電腦上寫一百萬個int

  • 通過writeInt(int i)方法花費了大約9秒鍾
  • 通過write(byte[] b)花費了大約2.3秒

在另一個使用JDK 7和完全不同的機器的環境中,我得到了類似的結果。

writeInt(int i)方法委托給本機write0(int b)方法,而write(byte[] b)委托給本機writeBytes

當我進行性能分析時,我注意到使用它時,大部分執行時間都花在了writeInt方法上。

有誰知道我為什么看到如此大的差異? 似乎writeInt效率較低。

RandomAccessFile實際上有兩個本地方法來寫入字節:

//writes an array
private native void writeBytes(byte b[], int off, int len) throws IOException;

//writes one byte
public native void write(int b) throws IOException;

方法writeInt(int)使用本機write(int)方法分別寫入每個字節,而write(byte [])使用本機writeBytes(byte [],int,int)方法。

writeInt方法執行4種方法調用來寫入傳遞的整數值的每個字節,另一種方法僅使用一個調用來寫入數組。 方法調用實際上是java中昂貴的操作:對於每次調用,JVM都會為操作數堆棧和局部變量數組分配額外的內存。

我不打算詳細介紹我所做的更改,但是您的測試有些缺陷。 我自由地進行了一些更新,並且也進行了一些測試:

@BenchmarkMode(value = { Mode.AverageTime })
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 2, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 2, time = 2, timeUnit = TimeUnit.SECONDS)
public class RandomAccessWriteFileTest {

    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder().include(RandomAccessWriteFileTest.class.getSimpleName())
                .jvmArgs("-ea")
                .shouldFailOnError(true)
                .build();
        new Runner(opt).run();
    }

    @Benchmark()
    @Fork(1)
    public long benchamrkWriteDirectInt(BenchmarkPlainIntSetup setupTest) {
        try {
            setupTest.raf.writeInt(6969);
            return setupTest.raf.length();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Benchmark()
    @Fork(1)
    public long benchamrkWriteConvertedInt(BenchmarkConvertedIntSetup setupTest) {
        try {
            setupTest.raf.write(intToBytes(6969));
            return setupTest.raf.length();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] intToBytes(int i) {
        byte[] result = new byte[4];

        result[0] = (byte) (i >> 24);
        result[1] = (byte) (i >> 16);
        result[2] = (byte) (i >> 8);
        result[3] = (byte) i;

        return result;
    }

    @State(Scope.Thread)
    static public class BenchmarkConvertedIntSetup {

        public RandomAccessFile raf;

        public File f;

        @Setup(Level.Iteration)
        public void setUp() {
            try {
                f = new File("jmhDirectIntBenchamrk.ser" + ThreadLocalRandom.current().nextInt());
                raf = new RandomAccessFile(f, "rw");
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        @TearDown(Level.Iteration)
        public void tearDown() {
            f.delete();
        }
    }

    @State(Scope.Thread)
    static public class BenchmarkPlainIntSetup {

        public RandomAccessFile raf;

        public File f;

        @Setup(Level.Iteration)
        public void setUp() {
            try {
                f = new File("jmhDirectIntBenchamrk.ser" + ThreadLocalRandom.current().nextInt());
                raf = new RandomAccessFile(f, "rw");
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        @TearDown(Level.Iteration)
        public void tearDown() {
            f.delete();
        }
    }
}

絕對會有結果差異(每個操作的毫秒數)

 benchamrkWriteConvertedInt  0.008 
 benchamrkWriteDirectInt     0.026

不知道為什么(可能會在以后的一段時間中挖掘程序集來理解,但是我可以確認您的發現。很好的問題!)

這是使用最新的Java-8和Java-9 btw運行的

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM