.NET RemotingとWCFの性能比較

2017/06/27

.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 Comments:

コメントを投稿

Links to this post:

リンクを作成

<< Home