none
.NETソケット送受信について RRS feed

  • 質問

  • たびたび騒がしております。NetworkStreamを使って、
     .NETの送受信を行っておりますが、パフォーマンスが思った通りの
     性能が出なくこまっております。
     原因はほぼ特定しております。
     受信データの取り出し処理、socketFormattersの Deserializeで時間かかっております。
     データサイズと関係なく、ほぼ毎回380ミリ秒かかっております。
     ※しかし、SerializeしてFlushしているところは40ミリ秒程度です。←不思議?
     ※格納しているDataSetは型が付いていないデータセットです。
     ※送受信バッファサイズを32Kにしています。
    △質問のゴール:
    ①Deserializeのパフォーマンスを改善する。
    現在380ミリ秒掛る処理を⇒Serializeの40ミリ秒に近づけたい
    ※NetworkStreamを使わないで、ネーティブのソケット処理を実装する方法もあると思いますが、
    いま検討対象外します。

    △処理サンプル

     Private socketStream As NetworkStream
     Private socketHandle As TcpClient
     Private socketFormatters As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
       
        '受信処理の抜粋
        '宣言部
        'クライアント⇒サーバにまたはサーバ⇒クライアントに文字列を送信する。
    ’dsResualtDataSetは受信したデータを格納するDataSet
    socketStream = socketHandle.GetStream()
    dim obj as object = socketFormatters.Deserialize(socketStream)
    dsResualtDataSet = CType(socketFormatters.Deserialize(socketStream), DataSet)

    ’送信部分の処理の抜粋
    ’dsSendDataSet は DataSet、なかに送信データを格納している
    socketStream = socketHandle.GetStream()
    dsSendDataSet.RemotingFormat = SerializationFormat.Binary
    socketFormatters.Serialize(socketStream, dsSendDataSet)
    socketStream.Flush()

    △環境:
    Visual Studio 2005
    .NET Framework 2.0 SP2
    サーバ:Windows2003R2SP2 .NET Framework 2.0 SP2
    クライアント:XPSP3 .NET Framework 2.0 SP2
    回線:LAN、100Base、クロース環境です。

    2010年5月26日 0:40

回答

  • 問題がデシリアライズ単体で低速であるのか、ネットワークからのデシリアライズが低速であるのかを特定したほうがよいかもしれませんね。単純にメモリ上でシリアライズ・デシリアライズを行う場合とくらべてどれぐらい影響しているか確認してみてはいかがでしょう?

    デシリアライズはシリアライズよりコストのかかる操作であろうことは予想がつきますので、ネットワークとは無関係にデシリアライズに時間がかかっているだけかもしれません。

    バッファを設定されているということなので違うかと思いますが、デシリアライズ時に小さな単位での読み書きが発生することが原因になっているならば、BufferedStream を経由することで改善がみられる場合もあるでしょう。

    そこまで確認しおえて、ネットワークとデシリアライズの組み合わせだけで問題が発生している・・・ということになった場合は、いったん MemoryStream などに受けてからデシリアライズすることで改善できるかもしれません。

    2010年5月26日 3:43

すべての返信

  • 問題がデシリアライズ単体で低速であるのか、ネットワークからのデシリアライズが低速であるのかを特定したほうがよいかもしれませんね。単純にメモリ上でシリアライズ・デシリアライズを行う場合とくらべてどれぐらい影響しているか確認してみてはいかがでしょう?

    デシリアライズはシリアライズよりコストのかかる操作であろうことは予想がつきますので、ネットワークとは無関係にデシリアライズに時間がかかっているだけかもしれません。

    バッファを設定されているということなので違うかと思いますが、デシリアライズ時に小さな単位での読み書きが発生することが原因になっているならば、BufferedStream を経由することで改善がみられる場合もあるでしょう。

    そこまで確認しおえて、ネットワークとデシリアライズの組み合わせだけで問題が発生している・・・ということになった場合は、いったん MemoryStream などに受けてからデシリアライズすることで改善できるかもしれません。

    2010年5月26日 3:43
  • 参考までに、デシリアライズそのものが遅いという話になった場合、標準ではシリアライザがデシリアライズのために protected なメソッドを外部から呼び出したりしますので、そのあたりがボトルネックになっているかもしれません。

    2010年5月28日 3:59
  • Takaokaさん
    アドバイスありがとうございます。

    △メモリ上シリアライズ・デシリアライズやってみましたが、
    パフォーマンスがほぼ変わっていないです。やはりDataSetでそんなに重いものでしょうかね?

    □DataSetではなく、独自でCustom Class定義してシリアライズ・デシリアライズやってみたら
    パフォーマンスが10倍ぐらい早くなりました。しかし、これは最後最後の手段と考えています。
    ソケット送受信で数十種類の送受信パターンがあるので、プログラム改造は大変になります。

    ▲すみません、勉強不足でprotected の意味をよく理解できませんでしたが、
    なんらかの方法でDataSetの定義を変えられるということでしょうか

    ※簡単にまとめると
    いまは明らかにDataSetデシリアライズがボトルネックになっております。
    独自クラスのデシリアライズはDataSetより10倍ぐらい速いです。

    2010年5月31日 1:22