none
.Net RemotingにおけるOutOfMemoryException RRS feed

  • 質問

  • がっちんと申します。

    お世話になります。

     

    現在、.Net Remotingを利用したクライアント/サーバ アプリケーションを開発しています。

    このアプリケーションではクライアントからサーバに対してファイルのアップロードを行っており、

    ファイルをByte[]に読み込んだ後、リモーティングのクラスメソッドにてByte[]を送信しています。

     

    しかし、小さなファイルは問題なく動作するのですが、やや大容量のファイル(80MB)で実行すると

    OutOfMemoryExceptionが出てしまいます。実行環境のPCはメモリが2GBあり、普段は滅多に

    OutOfMemoryExceptionはでることがないのですが、.Net Remotingではすぐにこれが出現しま

    す。

     

    .Net Remotingでは利用可能なメモリリソースが制限されているのでしょうか?

    あるいは、僕のプログラムコードに不具合があるのでしょうか?

    また、根本的に、この様なファイルアップロード処理で.Net Remotingを使用することは間違って

    いて、やはりTCPの通信APIを使うべきなのでしょうか?

     

    もし何かアドバイスがあればよろしくお願いします。

    主な部分のプログラムコードは以下の通りです。

     

    (OS:WinXP, VisualStudio2005 .NET Framework2.0を利用)

     

    ■クライアント側

    HttpServerChannel clientChannel = new HttpServerChannel();
    ChannelServices.RegisterChannel(clientChannel, false);

    NewTaskObject msg = (NewTaskObject)Activator.GetObject(typeof(NewTaskObject),

    http://192.168.0.100:9999/newTask);

    //タイムアウトの設定
    System.Collections.IDictionary props = ChannelServices.GetChannelSinkProperties(msg);
    props["Timeout"] = 100000;

    //アップロードするファイル

    string fileName = "D:\testFile";

    byte[] fileByte = File.ReadAllBytes(fileName);

    //リモーティングの実行

    msg.SendMsg(fileName,fileByte);

     

    ■サーバ側

    public void StartServer(){

    HttpServerChannel servChannel = new HttpServerChannel("Task", 9999);
    ChannelServices.RegisterChannel(servChannel, false);
    // イベントを登録
    NewTaskObject msg = new NewTaskObject();
    msg.eventCall += new NewTaskObject.CallHandler(msg_eventCall);
    RemotingServices.Marshal(msg, "newTask", typeof(NewTaskObject));

    }

     

    public void msg_eventCall(string fileName,byte[] fileByte){

    FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
    fs.Write(fileByte, 0, fileByte.Length);
    fs.Close();

    ・・・・・・・・

    ・・・・・・・・

     

    }

     

    2007年10月11日 4:17

回答

  • ためしにバイナリフォーマッタでやってみたらどうなります?

    SoapFormatterは結構メモリ食いなので、想像以上の連続メモリを消費している可能性もある気がします。

    BinaryFormatterだと、byte配列なんかはかなり効率よく処理できた気がします。

     

    ただ、Remotingでは送り側も受け側もオンメモリでシリアライズ前、作業領域、シリアライズ後のメモリを使用するので、あまり大きなデータの直接的な受け渡しには向きません。

    例えばバイナリフォーマッタを使用しても送り側と受け側で合わせて、少なくともシリアライズ前、シリアライズ後、デシリアライズ前、デシリアライズ後分のメモリが同時使用される可能性があります(同一マシンで試した場合)。

     

    まあ、ASP.NETでのファイルのアップロードも確かオンメモリで一気に処理してしまいますし、ダウンロードも単純にやれば同じようなことにはなりますが。

     

    簡単にやるなら、データをレンジ分けして分割で送信するなどすれば、ある程度対応はできると思います。

    2007年10月13日 1:15
  •  なちゃ さんからの引用

    ためしにバイナリフォーマッタでやってみたらどうなります?

    SoapFormatterは結構メモリ食いなので、想像以上の連続メモリを消費している可能性もある気がします。

    BinaryFormatterだと、byte配列なんかはかなり効率よく処理できた気がします。

     

    HttpServerChannelのSoapFormatterを使っていたのですが、アドバイス通りTcpServerChannelで

    BinaryFormatterを使用することで、メモリ消費が格段に減りOutOfMemoryが出なくなり問題を解決

    することができました。

     

    とても勉強になりました。

    ありがとうございました。

    2007年10月18日 3:13

すべての返信

  •  がっちん さんからの引用
    しかし、小さなファイルは問題なく動作するのですが、やや大容量のファイル(80MB)で実行すると

    OutOfMemoryExceptionが出てしまいます。実行環境のPCはメモリが2GBあり、普段は滅多に

    OutOfMemoryExceptionはでることがないのですが、.Net Remotingではすぐにこれが出現しま

    す。

     

    私は Remoting は普段使用していないのでどちらか知らないのですが,.NET Remoting の場合,サーバサイドで例外が発生した場合も,ローカルで例外が起きたように見えるのでしょうか? それとも サーバサイドで発生した例外は,クライアントサイドでは何かラップされて見えるのでしょうか?

     

    「実行環境のPCはメモリが2GBあり」とありますが,サーバ/クライアントは同一の PC なのか否か,OutOfMemoryException の原因はサーバサイドかクライアントサイドか,などは注意してみた方がいいのではないでしょうか?

    2007年10月12日 9:08
  • ためしにバイナリフォーマッタでやってみたらどうなります?

    SoapFormatterは結構メモリ食いなので、想像以上の連続メモリを消費している可能性もある気がします。

    BinaryFormatterだと、byte配列なんかはかなり効率よく処理できた気がします。

     

    ただ、Remotingでは送り側も受け側もオンメモリでシリアライズ前、作業領域、シリアライズ後のメモリを使用するので、あまり大きなデータの直接的な受け渡しには向きません。

    例えばバイナリフォーマッタを使用しても送り側と受け側で合わせて、少なくともシリアライズ前、シリアライズ後、デシリアライズ前、デシリアライズ後分のメモリが同時使用される可能性があります(同一マシンで試した場合)。

     

    まあ、ASP.NETでのファイルのアップロードも確かオンメモリで一気に処理してしまいますし、ダウンロードも単純にやれば同じようなことにはなりますが。

     

    簡単にやるなら、データをレンジ分けして分割で送信するなどすれば、ある程度対応はできると思います。

    2007年10月13日 1:15
  • アドバイスをいただきありがとうございます。

     

    >>NyaRuRuさん

    Remotingでは、サーバ側でエラーが発生するとサーバ側でまずなんらかのException

    がでます。その影響でクライアント/サーバ間のHTTPやTCPで接続されたコネクションが遮断

    されるとクライアント側でRemotingExceptionが発生します。

    今回はサーバ側でもデバックモードでアプリケーションを起動しエラーの内容を確かめたところ

    OutOfMemoryExceptionが発生していました。PCのメモリはサーバPCもクライアントPCも2GB

    となっています。

      また、同一PCでサーバ/クライアントのRemotingをやってみたところやはりうまくいかずエラーの

    原因がOutOfMemoryExceptionとなっていました。

     

    >>なちゃさん

    なるほど、バイナリフォーマッタで試しにやってみることにします。

    またレンジ分けで分割送信も試してみることにします。

     

    またのちほどご報告させていただきたいと思います。

    2007年10月15日 1:56
  •  なちゃ さんからの引用

    ためしにバイナリフォーマッタでやってみたらどうなります?

    SoapFormatterは結構メモリ食いなので、想像以上の連続メモリを消費している可能性もある気がします。

    BinaryFormatterだと、byte配列なんかはかなり効率よく処理できた気がします。

     

    HttpServerChannelのSoapFormatterを使っていたのですが、アドバイス通りTcpServerChannelで

    BinaryFormatterを使用することで、メモリ消費が格段に減りOutOfMemoryが出なくなり問題を解決

    することができました。

     

    とても勉強になりました。

    ありがとうございました。

    2007年10月18日 3:13