1

私のシステムでは、TCP ソケットを介して非常に大量のデータとメタデータを送信しています。さまざまなメタデータと 20 バイト配列を含む単一のオブジェクトを送信しています。これまで、BufferedOutputStream を囲む ObjectOutputStream を使用して、小さな例 (130kB 配列) に取り組んできました。目標の 67MB 配列に到達しようとしましたが、ObjectOutputStream はそれほど多くのデータを処理できません。1MB の配列を送信できましたが、writeObject() が 2MB でハングアップしました。

DataOutputStream の方が速いと聞いたことがありますが、メタデータをバイトとしてエンコードし、反対側でデコードする必要はありません。非常に大きなオブジェクトをすばやく送信できる良い代替手段はありますか?

編集:

各書き込みメソッドの後に、すでに reset() を使用しています。私は現在、20 個の配列と多数のメタデータ フィールドを含む独自の Message オブジェクトを含む単一の SignedObject を送信しています。便利なのでまとめておいたほうがいいのですが、分別しかないことも承知しています。そうは言っても、すべての送信が安全であることを確認する必要があります。

アップデート:

それで私は昼食に行き、戻ってきて、送信側と受信側のどちらで問題が発生しているかを調べてみることにしました。そして、それは決してハングアップしませんでした。ヒープを使い果たすまで、最大 4MB の配列を正常に送信し続けることができました (これは無関係であり、より優れたコンピューターまたはより効率的な処理が必要であることを意味します)。それで、問題は解決したと思いますか?これを伝えるためのより良い方法が必要ないという意味ではありません。また、これを更新するとすぐに、再び機能しなくなると思います...

4

1 に答える 1

2

非常に大きなオブジェクトをすばやく送信できる良い代替手段はありますか?

送信されるオブジェクト間で、reset() を指定して ObjectOutputStream を使用します。メモリが数 MB しかない場合 (この場合はもっと多くのメモリを用意する必要があります) を除き、問題は発生しません。

ObjectOutputStream は、自分でバイトをエンコードする場合に比べてかなり遅いですが、エンコードをうまく処理できます。ネットワークのアップロード速度が制限要因である可能性が高くなります。この例では、約 600 Mb/s で送信していますが、ほとんどのブロードバンド接続は約 500 kb/s (約 1000 倍遅い) です。

ServerSocket ss = new ServerSocket(0);
Socket s = new Socket("localhost", ss.getLocalPort());
final Socket s2 = ss.accept();
ss.close();

new Thread(new Runnable() {
    @Override
    public void run() {
        int count = 0;
        long start = System.nanoTime();
        try {
            ObjectInputStream in = new ObjectInputStream(
                    new InflaterInputStream(s2.getInputStream()));
            while (in.readObject() != null) count++;
            s2.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        long time = System.nanoTime() - start;
        System.out.printf("Read %,d objects in %.3f seconds%n", count, time / 1e9);
    }
}, "reader").start();
ObjectOutputStream oos = new ObjectOutputStream(
        new DeflaterOutputStream(s.getOutputStream()));
for (int i = 0; i < 20; i++) {
    byte[] bytes = new byte[67 * 1000 * 1000];
    oos.writeObject(bytes);
    oos.reset();
}
oos.writeObject(null); // poison pill
oos.close();
s.close();

版画

Read 20 objects in 21.644 seconds
于 2012-12-12T17:05:16.790 に答える