4

java.nio.charset.Charset.decode(..)/を行うためのより高速な方法を知っている人encode(..)はいますか?

現在、私が使用しているテクノロジーのボトルネックの 1 つです。

[編集] 具体的には、私のアプリケーションでは、1 つのセグメントを Java ソリューションから JNI ソリューションに変更しました (使用していた Java テクノロジよりも、私のニーズに最も適した C++ テクノロジがあったため)。

この変更により、速度が大幅に低下しました (CPU とメモリの使用量が大幅に増加しました)。

私が使用した JNI ソリューションを詳しく調べると、Java アプリケーションは byte[] を介して C++ アプリケーションと通信しています。これらの byte[] は、Java 側から Charset.encode(..) によって生成され、C++ 側に渡されます。次に、C++ が byte[] で応答すると、Charset.decode(..) を介して Java 側でデコードされます。

これをプロファイラーに対して実行すると、Charset.decode(..) と Charset.encode(..) の両方に、JNI ソリューションの全実行時間と比較してかなり長い時間がかかっていることがわかります (JNI ソリューションのみをプロファイリングしたため、スケジュールが空いたら、後日、アプリケーション全体のプロファイルを作成します :-) )。

私の問題についてさらに読むと、それは Charset.encode(..) と decode(..) の既知の問題であり、Java7 で対処されているようです。ただし、いくつかの制約があるため、Java7 への移行は (今のところ) 私にとって選択肢ではありません。

誰かがJava5ソリューション/これに代わるものを知っているかどうかここで尋ねるのはなぜですか(申し訳ありませんが、これはJava5用であるともっと早く言及すべきでした)?:-)

4

3 に答える 3

6

encode()およびの javadoc ではdecode()、これらが便利なメソッドであることを明確にしています。たとえば、encode()の場合:

この文字セットで Unicode 文字をバイトにエンコードする簡易メソッド。

文字セット cs でこのメソッドを呼び出すと、式と同じ結果が返されます。

 cs.newEncoder()
   .onMalformedInput(CodingErrorAction.REPLACE)
   .onUnmappableCharacter(CodingErrorAction.REPLACE)
   .encode(bb); 

ただし、連続する呼び出し間でエンコーダーをキャッシュできるため、より効率的である可能性があります。

言語は少しあいまいですが、これらの便利なメソッドを使用しないことでパフォーマンスが向上する可能性があります。エンコーダーを一度作成して構成し、それを再利用します。

 CharsetEncoder encoder = cs.newEncoder()
   .onMalformedInput(CodingErrorAction.REPLACE)
   .onUnmappableCharacter(CodingErrorAction.REPLACE);

 encoder.encode(...);
 encoder.encode(...);
 encoder.encode(...);
 encoder.encode(...);

すでに答えを知っていると思っていても、javadoc を読むことには常に価値があります。

于 2010-01-20T00:04:07.500 に答える
2

最初の部分 - 一般に、配列を JNI コードに渡すのは悪い考えです。GC のため、Java は配列をコピーする必要があります。価値のあるケースでは、配列は2回コピーされます-JNIコードへの途中で、そして戻る途中で:)

そのため、Bufferクラス階層が導入されました。もちろん、Java 開発チームは、文字をエンコード/デコードするための優れた方法を作成しています。

Charser#newDecodera に従ってに変換するためCharsetDecoderに使用できるyou を返します。2 つの主なメソッド バージョンがあります。ByteBufferCharBufferCharset

CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
CharBuffer decode(ByteBuffer in)

最大のパフォーマンスを得るには、最初のものが必要です。内部に隠しメモリ割り当てはありません。

エンコーダー/デコーダーは内部状態を維持できることに注意する必要があるため、注意が必要です (たとえば、2 バイトのエンコーディングからマップし、入力バッファーに char の半分がある場合など)。また、エンコーダー/デコーダーはスレッドセーフではありません

于 2013-01-09T09:53:05.220 に答える
1

バイト配列内の文字列を「スクイーズ」する理由はほとんどありません。utf-16文字列をパラメーターとして受け取るC関数を作成することをお勧めします。このように、変換の必要はありません。

于 2010-01-21T09:42:29.147 に答える