2012-03-14 7 views
0

私は1 intと4 doubleを持つオブジェクトを持っています。ファイルを読み書きする際のパフォーマンスは最高です。シリアライゼーションX Java.nio

私は、シリアライズとFileChannelオブジェクトを使用して、ファイル内でこれらのオブジェクトの500万を書き込むパフォーマンスを比較しました。

シリアライズでは、次の方法でファイルを読み書きしました。

public void print() throws IOException, ClassNotFoundException{  
    ObjectInputStream input = new ObjectInputStream(new FileInputStream(this.filePath));     
    try {   
     while(true) {    
      this.sb = (Sbit) input.readObject(); 
      //System.out.println(this.sb.toString()); 
     } 
    } 
    catch (EOFException eofException) { 
     return; 
    } 
    catch (IOException ioException) { 
     System.exit(1); 
    } 
    finally { 
     if(input != null) 
      input.close(); 
    } 

} 

public void build() throws IOException {   
    ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(this.filePath)); 
    try {   
     Random random = new Random(); 
     for (int i = 0; i<5000000; i++) { 
      this.sb = new Sbit(); 
      this.sb.setKey(i); 
      this.sb.setXMin(random.nextDouble()); 
      this.sb.setXMax(random.nextDouble()); 
      this.sb.setYMin(random.nextDouble()); 
      this.sb.setYMax(random.nextDouble()); 

      output.writeObject(this.sb); 
     }   
    } 
    catch (IOException ioException) { 
     System.exit(1); 
    } 
    finally { 
     try { 
      if(output != null) 
       output.close(); 
     } 
     catch (Exception exception) { 
      exception.printStackTrace(); 
      System.exit(1); 
     } 
    }  
} 

java.nioのを使用していたものの:

public void print() throws IOException {  
    FileChannel file = new RandomAccessFile(this.filePath, "rw").getChannel(); 
    ByteBuffer[] buffers = new ByteBuffer[5]; 
    buffers[0] = ByteBuffer.allocate(4); // 4 bytes to int 
    buffers[1] = ByteBuffer.allocate(8); // 8 bytes to double 
    buffers[2] = ByteBuffer.allocate(8);  
    buffers[3] = ByteBuffer.allocate(8); 
    buffers[4] = ByteBuffer.allocate(8); 

    while (true) { 
     if(file.read(buffers[0]) == -1)  // Read the int, 
      break;         // if its EOF exit the loop 

     buffers[0].flip(); 

     this.sb = new Sbit(); 
     this.sb.setKey(buffers[0].getInt()); 

     if(file.read(buffers[1]) == -1) { // Read the int primary value 
      assert false;     // Should not get here! 
      break;       // Exit loop on EOF 
     } 
     buffers[1].flip(); 

     this.sb.setXMin(buffers[1].getDouble()); 

     if(file.read(buffers[2]) == -1) { 
      assert false;     
      break;       
     } 
     buffers[2].flip(); 

     this.sb.setXMax(buffers[2].getDouble()); 

     if(file.read(buffers[3]) == -1) { 
      assert false;     
      break;       
     } 
     buffers[3].flip(); 

     this.sb.setYMin(buffers[3].getDouble()); 
     if(file.read(buffers[4]) == -1) { 
      assert false;     
      break;       
     } 
     buffers[4].flip(); 

     this.sb.setYMax(buffers[4].getDouble()); 

     for(int i = 0; i < 5; i++) 
      buffers[i].clear(); 

    } 

} 


public void build() throws IOException {  
    FileChannel file = new RandomAccessFile(this.filePath, "rw").getChannel();  

    Random random = new Random(); 
    for (int i = 0; i<5000000; i++) { 
     this.sb = new Sbit(); 
     this.sb.setKey(i); 
     this.sb.setXMin(random.nextDouble()); 
     this.sb.setXMax(random.nextDouble()); 
     this.sb.setYMin(random.nextDouble()); 
     this.sb.setYMax(random.nextDouble()); 

     ByteBuffer[] buffers = new ByteBuffer[5]; 
     buffers[0] = ByteBuffer.allocate(4); // 4 bytes to into 
     buffers[1] = ByteBuffer.allocate(8); // 8 bytes to double 
     buffers[2] = ByteBuffer.allocate(8); 
     buffers[3] = ByteBuffer.allocate(8); 
     buffers[4] = ByteBuffer.allocate(8); 

     buffers[0].putInt(this.sb.getKey()).flip(); 
     buffers[1].putDouble(this.sb.getXMin()).flip(); 
     buffers[2].putDouble(this.sb.getXMax()).flip(); 
     buffers[3].putDouble(this.sb.getYMin()).flip(); 
     buffers[4].putDouble(this.sb.getYMax()).flip(); 
     try { 
      file.write(buffers); 
     } 
     catch (IOException e) { 
      e.printStackTrace(System.err); 
      System.exit(1); 
     } 

     for(int x = 0; x < 5; x++) 
      buffers[x].clear(); 

    } 
} 

しかし、私はjava.nioの上について多くを読んで、それがより良いパフォーマンスを持っているからこそ、それを使用しようとしました。しかし、それは私の場合に起こったことではありません。ファイルを書き込むには

次(java.nioの)だった:

ファイルサイズ:ミリ秒単位で175メガバイト 時間:

ファイルサイズ:

シリアライズを使用します: 200MB ミリ秒単位の時間:

このファイルの閲覧に

、(java.nioの)を以下の通りであった:ミリ秒単位

時間:

をシリアル化を使用して:ミリ秒単位

時間:

java.nioで何か問題が起きていますか?私は同じバイナリファイルに書きたいと思います。効率的にファイルを書き込む別の方法がありますか?実際にオブジェクトを直列化するのが最善の方法ですか?

ありがとうございます。

+1

1つのByte Bufferを使用してから、結果を出力する前に 'putInt' /' putDouble'を呼び出してみてください。すべてのオブジェクトを作成する時間を節約できます。 –

+0

@JohnHaagerどうすればいいですか?このような? http://www.kodejava.org/examples/594.html。そしてそれを読む方法は? –

+0

本質的に、はい。あなたはそれに入れたいすべてのデータを保持するのに十分な大きさのバイトバッファを宣言し、今のようにそれにデータを入れます。完了したら、バッファを反転して書き出します。それを読み込む準備ができたら、ディスクからバイトバッファにデータを読み込み、それを反転して、 'getInt' /' getDouble'を使ってデータを読み込みます。 –

答えて

1

複数のByteBuffersを使用する代わりに、すべてのデータを格納できるだけの大きさの1バイトバッファを宣言します。あなたが今のようにそれにデータを入れてください。完了したら、バッファを反転して書き出します。それを読み込む準備ができたら、ディスクのデータをバイトバッファに読み込んで反転させた後、getInt/getDoubleを使用してデータを読み込みます。

0

私は自分でシリアル化しようとはしませんでしたが、kryoで良い結果が得られました。標準のJavaシリアル化よりもはるかに高速です。

+0

「kryo」は、java.nioパッケージのByeBufferオブジェクトを使用します。次に、java.nioまたは標準のJavaシリアル化を使用しますか? –

+0

AFAIK ByteBufferを使用できますが、私の実装ではObjectBufferと呼ばれるように "コンビニエンスクラス"を使用します。 これは組み込みのObjectOutputStream.writeObject()よりもはるかに高速だと言っています。 –

2

各ByteBufferが最大8バイトである25,000,000 ByteBufferオブジェクトを作成しています。それは非常に非効率です。

は、次のようにあなたが同じのByteBufferを使用することができますループ内

(文の前)ループの外で38バイトにそれを割り当てることによってだけのByteBufferを作成します。

buffer.clear(); 

    buffer.putInt(this.sb.getKey()); 
    buffer.putDouble(this.sb.getXMin()); 
    buffer.putDouble(this.sb.getXMax()); 
    buffer.putDouble(this.sb.getYMin()); 
    buffer.putDouble(this.sb.getYMax()); 

    buffer.flip(); 

    try 
    { 
    file.write(buffer); 
    } 
    catch (IOException ex) 
    { 
    ex.printStackTrace(); 
    //etc... 
    } 

    buffer.flip(); 

試してみてください。改善が見られる場合はお知らせください。

+0

ありがとう、しかし@ジョンHaagerはより速く反応しました。 –

関連する問題