.NET RemotingよりWCFのほうが遅いという噂もあるようなので、絶対値がどれぐらいなのかを調べるついでに、.NET RemotingとWCFとで比較してみた。
条件は以下の通り
- 同一マシン内で、IPCにより通信を行う。
- クライアントとサーバは別プロセスとする
- クライアント側からサーバ側の手続きを呼び出す処理の速度を比べる
- Releaseモードでコンパイルする。
- F#4.1、.NET Framework 4.7で実行する
昨日とほぼ同じだが、.NET RemotingとWCFのコードを以下に示す。
■.NET Remoting版
-----------------------------------------------------------------
open System open System.Runtime.Remoting open System.Runtime.Remoting.Channels open System.Runtime.Remoting.Channels.Ipc open System.Threading let LoopCount = 100000UL // サーバからクライアントに対して公開されるオブジェクト type CSharedObject() = inherit MarshalByRefObject() member this.foo arg = ( arg / 2UL ) // サーバ側の処理 let Server () = ChannelServices.RegisterChannel( new IpcServerChannel "test1", true ) let rSharedObject = new CSharedObject() RemotingServices.Marshal( rSharedObject, "test2", typeof< CSharedObject > ) |> ignore System.Threading.Thread.Sleep 60000 // クライアント側の処理 let Client () = // サーバ側で公開されているオブジェクトを取得する ChannelServices.RegisterChannel( new IpcClientChannel(), true ) let rSharedObject = Activator.GetObject( typeof< CSharedObject >, "ipc://test1/test2" ) :?> CSharedObject let rec foo cnt sum = if cnt < LoopCount then foo ( cnt + 1UL ) ( sum + ( rSharedObject.foo cnt ) ) else sum for i = 1 to 5 do let StartTime = DateTime.Now printf "%u\n" ( foo 0UL 0UL ) let ElapseTime = ( DateTime.Now - StartTime ).TotalMilliseconds printf "time=%f(ms), count/sec=%f\n" ElapseTime ( ( float LoopCount ) / ElapseTime * 1000.0 ) [<EntryPoint>] let main argv = if argv.[0] = "server" then Server () else Client () 0
-----------------------------------------------------------------
■WCF版
-----------------------------------------------------------------
open System open System.ServiceModel open System.Threading let g_Address = "net.pipe://localhost/test" let LoopCount = 100000UL // クライアントに公開されるオブジェクトのインタフェース [<ServiceContract()>] type public IRemote = [<OperationContract(Name="Hello")>] abstract member Hello : arg:uint64 -> uint64 // 遠隔手続きを実装するクラス type public Remote() = interface IRemote with member this.Hello arg = ( arg / 2UL ) // サーバ側の処理 let Server () = let host = new ServiceHost( typeof<Remote>, new Uri( "net.pipe://localhost" ) ) host.AddServiceEndpoint( typeof<IRemote>, new NetNamedPipeBinding( NetNamedPipeSecurityMode.None ), g_Address ) |> ignore host.Open(); Threading.Thread.Sleep 60000 // クライアント側の処理 let Client () = let proxy = ChannelFactory<IRemote>.CreateChannel( new NetNamedPipeBinding( NetNamedPipeSecurityMode.None ), new EndpointAddress( g_Address ) ) let rec foo cnt sum = if cnt < LoopCount then foo ( cnt + 1UL ) ( sum + ( proxy.Hello cnt ) ) else sum for i = 1 to 5 do let StartTime = DateTime.Now printf "%u\n" ( foo 0UL 0UL ) let ElapseTime = ( DateTime.Now - StartTime ).TotalMilliseconds printf "time=%f(ms), count/sec=%f\n" ElapseTime ( ( float LoopCount ) / ElapseTime * 1000.0 ) [<EntryPoint>] let main argv = if argv.[0] = "server" then Server () else Client () 0
-----------------------------------------------------------------
これを実行してみる。
.NET Remotingの実行結果
2499950000 time=7941.328300(ms), count/sec=12592.351836 2499950000 time=7799.342400(ms), count/sec=12821.593779 2499950000 time=7746.714100(ms), count/sec=12908.698928 2499950000 time=7709.778300(ms), count/sec=12970.541578 2499950000 time=7731.699700(ms), count/sec=12933.766685
"2499950000"の出力は最適化させないように、無理にでも処理結果を使うようにしているだけであって、意味はない。
とりあえず、1秒間に1万2千回程度呼び出しができるようだ。
次はWCFの実行結果
2499950000 time=4733.906600(ms), count/sec=21124.202155 2499950000 time=4538.663200(ms), count/sec=22032.919297 2499950000 time=4550.678500(ms), count/sec=21974.745085 2499950000 time=4541.667300(ms), count/sec=22018.345553 2499950000 time=4558.723600(ms), count/sec=21935.964707
WCFだと秒間で2万1千回程度実行できているように見える。
よくわからないが、.NET RemotingよりWCFのほうが早い。
何か設定や指定が悪いのか、あるいは.NETのバージョンが上がってWCFの最適化が進んでいるためか、原因は知らんが、まぁこの程度だということを前提に考えておこう。
0 件のコメント:
コメントを投稿