-1

オブジェクトを取得してbyte[]に変換するこの小さなコードがあります。C#4.0を使用します。速度、次にメモリ使用量に関してこれをさらに最適化できますか?小さな変更でも素晴らしいでしょう-これを毎秒数千回以上呼び出します。

    public static byte[] ObjectToByteArray(object obj)
    {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();

        using (ms)
        {
            bf.Serialize(ms, obj);  
        }

        return ms.ToArray();
    }
4

4 に答える 4

3

これをさらに最適化したい場合、最初に知る必要があるのは、現在最も多くの時間を費やしている場所です。これをプロファイラーで実行しましたか?結果はどうでしたか?

また、「これを最適化することで、ユーザーにどのような具体的なメリットがもたらされるのか?」と自問することもあります。言い換えれば、私がこれを最適化しているのは、私がエンジニアとしてコードを完成させたいからなのか、それとも私がソリューションを提供している人々に真の利益をもたらすからなのか?

実際のシリアライゼーションの実行にほとんどの時間を費やしているのではないかと思います。別のシリアライザーに変更すると、おそらく最大のメリットが得られます。代替のより高速なシリアライザーについては、次の質問を参照してください。

.NET での高速でコンパクトなオブジェクトのシリアル化

于 2012-06-24T17:43:28.723 に答える
2

問題は、 BinaryFormatter がリフレクションを使用してオブジェクトのフィールドを読み取ることです。1 つのフィールドを持つ単純なクラスがあるとします。

[Serializable]
public class Test
{
    public int A;
}

BinaryFormatter を使用してそれらの配列をシリアル化すると、Test の各インスタンスに対して次のような処理が行われます。

int val = (int)typeof(Test).GetField("A").GetValue(obj);
var bytes = BitConverter.GetBytes(val);
stream.Write(bytes, 0, bytes.Length);

GetField() の呼び出しにはかなりの時間がかかります。次の 3 つの方法を使用して、速度を大幅に向上させることができます。

  1. すべてを手動でシリアル化します。このコードに似たもの:

    void SimpleSerialize(Stream stream, Test[] arr)
    {
        foreach (var obj in arr)
        {
            var bytes = BitConverter.GetBytes(obj.A);
            stream.Write(bytes, 0, bytes.Length);
        }
    }
    
  2. Reflection.Emit 機能を使用して、オンザフライでカスタム シリアル化クラスを生成します。これはより一般的で「クリーン」ですが、多くの労力が必要です。

  3. 問題がなければ、ニーズに合ったサードパーティのシリアライザーを使用してください

于 2012-06-24T19:28:56.317 に答える
1

このコードを改善するためにできることはほとんどありません。単純なオブジェクトを扱っている場合は、 を に置き換え、各フィールド/プロパティを手動でシリアル化することで、このコードを改善BinaryFormatterできBinaryWriterます。これは取得できる最速のシリアル化です。ただし、これは、このコードが何らかの形でアプリケーションのボトルネックであると実験的に判断した場合にのみ実行する必要がある極端な方法です。そうしないと、マイクロ最適化を行って時間を無駄にする可能性があります。

于 2012-06-24T17:42:44.557 に答える
0

ThreadStatic byte[]をインスタンス フィールドとして定義し、それをキャッシュとして使用します。このキャッシュ オブジェクトをメモリ ストリームでラップします。コードに書かれているように使用するMemoryStreamと、大量の割り当て、再割り当て、配列のコピーの手順が実行され、MemoryStreamサイズ変更が可能になります。考慮すべきガベージ コレクションのコストもあります。

おそらく、これがうまく機能するかどうかはわかりませんが、両方の書式設定オブジェクトをThreadStaticインスタンス フィールドとしてキャッシュしてください。

PS、間違いだと思いますが、MemoryStream使用する前に廃棄していることに注意してください。

于 2012-06-24T19:13:50.513 に答える