web-dev-qa-db-ja.com

ASCII byte []を文字列に変換

ASCII文字を含むbyte []をlog4jに渡して、明白な表現を使用してファイルに記録されるようにしようとしています。byt[]を渡すだけで、オブジェクトとログはほとんど役に立たないnew String(byte[] data)を使用して文字列に変換しようとすると、アプリケーションのパフォーマンスが半分になります。

それらを文字列に変換する約30usの時間のペナルティを被ることなく、どのようにしてそれらを効率的に渡すことができますか?.

また、変換に時間がかかるのはなぜですか?

ありがとう。

編集

ここでレイテンシが最適であることを付け加えておきます。そうです、30usは違いを生みます!また、これらの配列は、100から数千バイトまでさまざまです。

19
jwoolard

実行したいことは、log4jが実際にメッセージをログに記録することを決定するまで、byte []配列の処理を遅らせることです。このようにして、たとえば、テスト中にDEBUGレベルでログを記録し、本番環境では無効にすることができます。たとえば、次のことができます。

final byte[] myArray = ...;
Logger.getLogger(MyClass.class).debug(new Object() {
    @Override public String toString() {
        return new String(myArray);
    }
});

Log4jが実際にメッセージをログに記録すると決定するまでtoStringメソッドは呼び出されないため、実際にデータをログに記録しない限り、速度のペナルティを支払う必要はありません。

現在、「明白な表現」が何を意味するのかわからないので、デフォルトの文字エンコーディングとしてバイトを再解釈することにより、文字列に変換することを意味すると想定しました。バイナリデータを扱っている場合、これは明らかに価値がありません。その場合、 Arrays.toString(byte []) を使用して、次の行に沿ってフォーマットされた文字列を作成することをお勧めします

[54, 23, 65, ...]
14

ASCIIは、算術演算やテーブル検索を行わずにUTF16との間で変換できる数少ないエンコーディングの1つなので、手動で変換することができます。

String convert(byte[] data) {
    StringBuilder sb = new StringBuilder(data.length);
    for (int i = 0; i < data.length; ++ i) {
        if (data[i] < 0) throw new IllegalArgumentException();
        sb.append((char) data[i]);
    }
    return sb.toString();
}

しかし、それが本当にis ASCIIであることを確認してください。そうしないと、ゴミになってしまいます。

17
finnw

Ifあなたのデータが実際にASCII(つまり、7ビットデータ)である場合、 new String(data, "US-ASCII") プラットフォームのデフォルトのエンコーディングに依存する代わりに、これはプラットフォームのデフォルトのエンコーディングとして解釈しようとするよりも速いかもしれません(UTF-8である可能性があり、より多くの内省)。

Charset インスタンスをキャッシュして new String(data, charset) 代わりに。

とは言っても、本当のASCIIデータが本番環境で見られたので、非常に長い時間です。

8
Joachim Sauer
1
Rubens Farias

半分のパフォーマンス?このバイト配列はどのくらいの大きさですか?たとえば1MBの場合、バイトから文字への "変換"(これは十分に高速であると想定されています)よりも、考慮する必要のある要素が確かにあります。 書き込み「ちょうど」100バイトではなく、1MBのデータ(byte[].toString()が生成する可能性があります)ログファイルへ明らかに時間がかかることになります。ディスクファイルシステムは、RAMメモリほど高速ではありません。

バイト配列の文字列表現を変更する必要があります。たぶんいくつかのより機密性の高い情報、例えば関連する名前(ファイル名?)、長さなど。結局のところ、そのバイト配列は実際にはを何を表していますか?

編集 "約30us"のフレーズを質問で見たことを思い出せません。質問してから5分以内ですが、これは実際にはマイクロ最適化であり、一般に「パフォーマンスの半分」になることはありません。 1秒間に100万回それらを書かない限り(それでも、なぜそれをしたいのですか?「ロギング」という現象を使いすぎていませんか?).

1
BalusC