14

バイナリ データ用の Java ベースのダウンローダーを開発しています。このデータは、テキストベースのプロトコル (UU エンコード) を介して転送されます。ネットワーク タスクにはnettyライブラリが使用されます。バイナリ データはサーバーによって何千もの小さなパケットに分割され、クライアント (つまり Java アプリケーション) に送信されます。

nettyからChannelBufferは、新しいメッセージ (データ)を受信するたびにオブジェクトを受け取ります。次に、そのデータを処理する必要があります。他のタスクに加えて、サーバーからのパッケージのヘッダー (HTTP ステータス行など) を確認する必要があります。そのために、配列ChannelBuffer.array()を受け取るために呼び出します。byte[]次に、この配列を文字列に変換し、new String(byte[])その内容を簡単に確認 (比較など) できます (ここでも、HTTP の「200」ステータス メッセージとの比較のように)。

私が書いているソフトウェアは複数のスレッド/接続を使用しているため、nettyから複数のパケットを並行して受信します。

Stringこれは通常は問題なく動作しますが、アプリケーションのプロファイリングを行っているときに、サーバーへの接続が良好でデータが非常に高速に受信されると、このオブジェクトへの変換がボトルネックのように見えることに気付きました。String(byte[])このような場合、CPU 使用率は 100% 近くになり、プロファイラーによると、このコンストラクターの呼び出しに非常に多くの時間が費やされます。

から に到達するためのより良い方法を検索したところChannelBufferString前者にもtoString()方法があることに気付きました。ただし、そのメソッドはString(byte[])コンストラクターよりもさらに低速です。

だから私の質問は:あなたの誰かが私がやっていることを達成するためのより良い代替手段を知っていますか?

4

3 に答える 3

16

おそらく、文字列変換を完全にスキップできますか? 比較値のバイト配列を保持する定数を使用し、String-to-String の代わりに array-to-array をチェックすることができます。

説明する簡単なコードを次に示します。現在、あなたは次のようなことをしています:

String http200 = "200";
// byte[] -> String conversion happens every time
String input = new String(ChannelBuffer.array());
return input.equals(http200);

多分これはより速いです:

// Ideally only convert String->byte[] once.  Store these
// arrays somewhere and look them up instead of recalculating.
final byte[] http200 = "200".getBytes("UTF-8"); // Select the correct charset!
// Input doesn't have to be converted!
byte[] input = ChannelBuffer.array();
return Arrays.equals(input, http200);
于 2013-10-11T19:48:21.177 に答える
2

あなたが行っているチェックのいくつかは、バッファの一部を見るだけかもしれません。String コンストラクターの代替形式を使用できる場合:

new String(byteArray, startCol, length)

これは、文字列に変換されるバイトがはるかに少ないことを意味する場合があります。

メッセージ内で「200」を探す例がその例です。

2

バイト配列の長さを手がかりとして使用できることに気付くかもしれません。一部のメッセージが長く、短いメッセージを探している場合は、長いメッセージを無視し、文字に変換しないでください。またはそのようなもの。

3

@EricGrunzkeが言ったことに加えて、バイトバッファを部分的に調べて一部のメッセージを除外し、それらをバイトから文字に変換する必要がないことを見つけます。

4

バイトが ASCII 文字の場合、サーバーのデフォルトの代わりに文字セット「ASCII」を使用すると、文字への変換が速くなる可能性があります。

new String(bytes, "ASCII")

その場合は速いかもしれません。

実際、物事をスピードアップする組織化された方法で、バイト文字を変換するための文字セットを選択して選択できる場合があります。

于 2013-10-11T19:56:02.073 に答える
0

何をしようとしているかに応じて、いくつかのオプションがあります。

  1. 応答ステータスを取得しようとしているだけの場合は、getStatus()を呼び出すことはできませんか? これはおそらく、文字列を取り出すよりも高速です。
  2. バッファを変換しようとしている場合は、それが ASCII であることを知っていると仮定して、データを byte[] のままにして、UUDecode メソッドを変換して、代わりに byte[] で動作するようにします。弦。

文字列変換の最大のコストは、バイト配列から文字列の内部 char 配列へのデータのコピーである可能性が最も高く、これを変換と組み合わせると、おそらく行う必要のない一連の作業になります。

于 2013-10-11T19:59:42.603 に答える