トップ回答者
.NETソケット送受信について

質問
-
たびたび騒がしております。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、クロース環境です。
回答
-
問題がデシリアライズ単体で低速であるのか、ネットワークからのデシリアライズが低速であるのかを特定したほうがよいかもしれませんね。単純にメモリ上でシリアライズ・デシリアライズを行う場合とくらべてどれぐらい影響しているか確認してみてはいかがでしょう?
デシリアライズはシリアライズよりコストのかかる操作であろうことは予想がつきますので、ネットワークとは無関係にデシリアライズに時間がかかっているだけかもしれません。
バッファを設定されているということなので違うかと思いますが、デシリアライズ時に小さな単位での読み書きが発生することが原因になっているならば、BufferedStream を経由することで改善がみられる場合もあるでしょう。
そこまで確認しおえて、ネットワークとデシリアライズの組み合わせだけで問題が発生している・・・ということになった場合は、いったん MemoryStream などに受けてからデシリアライズすることで改善できるかもしれません。
すべての返信
-
問題がデシリアライズ単体で低速であるのか、ネットワークからのデシリアライズが低速であるのかを特定したほうがよいかもしれませんね。単純にメモリ上でシリアライズ・デシリアライズを行う場合とくらべてどれぐらい影響しているか確認してみてはいかがでしょう?
デシリアライズはシリアライズよりコストのかかる操作であろうことは予想がつきますので、ネットワークとは無関係にデシリアライズに時間がかかっているだけかもしれません。
バッファを設定されているということなので違うかと思いますが、デシリアライズ時に小さな単位での読み書きが発生することが原因になっているならば、BufferedStream を経由することで改善がみられる場合もあるでしょう。
そこまで確認しおえて、ネットワークとデシリアライズの組み合わせだけで問題が発生している・・・ということになった場合は、いったん MemoryStream などに受けてからデシリアライズすることで改善できるかもしれません。
-
Takaokaさん
アドバイスありがとうございます。△メモリ上シリアライズ・デシリアライズやってみましたが、
パフォーマンスがほぼ変わっていないです。やはりDataSetでそんなに重いものでしょうかね?□DataSetではなく、独自でCustom Class定義してシリアライズ・デシリアライズやってみたら
パフォーマンスが10倍ぐらい早くなりました。しかし、これは最後最後の手段と考えています。
ソケット送受信で数十種類の送受信パターンがあるので、プログラム改造は大変になります。▲すみません、勉強不足でprotected の意味をよく理解できませんでしたが、
なんらかの方法でDataSetの定義を変えられるということでしょうか※簡単にまとめると
いまは明らかにDataSetデシリアライズがボトルネックになっております。
独自クラスのデシリアライズはDataSetより10倍ぐらい速いです。