WCF チャネルの生成と破棄にかかるコスト

WCF で、毎回チャネルを生成してサービスを呼び出した場合と、生成したチャネルを使い回した場合、どれくらい時間に差が出るのかを試してみました。

早速ですが、10回、100回、1000回連続してサービスを呼び出した結果は、下表の通りです。

場面 10回(ms) 100回(ms) 1000回(ms)
1度生成したチャネルを使い回し 16 146 1415
毎回チャネルを生成してサービス呼び出し 52 481 4519

3倍くらい開きがあります。でも、サービスを1つの処理で100回呼び出すなんてことは、まず無いでしょうね。気にしなくてもいいかな。

実験に使ったコードは次の通り。

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;

namespace CostSample
{
    class Program
    {
        private const int ROOP_COUNT = 1000;
        private const string ADDRESS = "net.tcp://localhost:8081/GreetingServce";

        static void Main(string[] args)
        {
            // サービス開始
            ServiceHost host = new ServiceHost(typeof(GreetingService));
            host.AddServiceEndpoint(typeof(IGreetingService),
                new NetTcpBinding(),
                ADDRESS);
            host.Open();

            // 初回だけ時間がかかるので、1回サービスを呼び出しておく
            IGreetingService channel1 = ChannelFactory<IGreetingService>.CreateChannel(
                new NetTcpBinding(),
                new EndpointAddress(ADDRESS));
            channel1.Greet("Foo");

            // チャネルを使い回した場合
            Stopwatch watch = new Stopwatch();
            watch.Start();
            for (int i = 0; i < ROOP_COUNT; i++)
            {
                channel1.Greet("Foo");
            }
            ((IChannel)channel1).Close();
            watch.Stop();
            Console.WriteLine("チャネル使い回し : {0} ms", watch.ElapsedMilliseconds);

            // チャネルを毎回生成した場合
            watch.Reset();
            watch.Start();
            for (int i = 0; i < ROOP_COUNT; i++)
            {
                IGreetingService channel2 = ChannelFactory<IGreetingService>.CreateChannel(
                    new NetTcpBinding(),
                    new EndpointAddress(ADDRESS));
                channel2.Greet("Foo");
                ((IChannel)channel2).Close();
            }
            watch.Stop();
            Console.WriteLine("チャネル毎回生成 : {0} ms", watch.ElapsedMilliseconds);

            host.Close();
            Console.ReadLine();
        }
    }

    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string Greet(string name);
    }

    public class GreetingService : IGreetingService
    {
        public string Greet(string name)
        {
            return string.Format("Hello, {0}!", name);
        }
    }
}

ROOP_COUNT 定数を変更して、サービスを呼び出す回数を変更しました。