WCF против .Net Remoting
согласно этой статье, WCF с именованными каналами является лучшим выбором для IPC, и он примерно на 25% быстрее, чем .Net Remoting.
У меня есть следующий код, который сравнивает WCF с именованными каналами с .Net Remoting:
[ServiceContract]
internal interface IRemote
{
[OperationContract]
string Hello(string name);
}
[ServiceBehavior]
internal class Remote : MarshalByRefObject, IRemote
{
public string Hello(string name)
{
return string.Format("Hello, {0}!", name);
}
}
class Program
{
private const int Iterations = 5000;
static void Main(string[] args)
{
TestWcf(Iterations);
TestRemoting(Iterations);
TestWcf(Iterations);
TestRemoting(Iterations);
TestWcf(Iterations);
TestRemoting(Iterations);
Console.ReadKey();
}
private static void TestRemoting(int iterations)
{
var domain = AppDomain.CreateDomain("TestDomain");
var proxy =
(IRemote)
domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");
Console.WriteLine("Remoting: {0} ms.", Test(proxy, iterations));
}
private static void TestWcf(int iterations)
{
var address = "net.pipe://localhost/test";
var host = new ServiceHost(typeof (Remote));
host.AddServiceEndpoint(typeof (IRemote), new NetNamedPipeBinding(), address);
host.Open();
var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
Console.WriteLine("Wcf: {0} ms.", Test(proxy, iterations));
host.Close();
}
private static double Test(IRemote proxy, int iterations)
{
var start = DateTime.Now;
for (var i = 0; i < iterations; i++)
{
proxy.Hello("Sergey");
}
var stop = DateTime.Now;
return (stop - start).TotalMilliseconds;
}
}
A получил следующие результаты для 5000 итераций:
Wcf: 14143 ms.
Remoting: 2232 ms.
Wcf: 14289 ms.
Remoting: 2130 ms.
Wcf: 14126 ms.
Remoting: 2112 ms.
Wcf примерно в 7 раз медленнее, чем .Net Remoting в этом тесте.
Я попытался:
- установите для режима безопасности значение None;
- установить InstanceContextMode в Single/PerCall;
- установить ConcurrencyMode в Single/Multiple;
но результаты одинаковы.
Кто-нибудь знает, что я делаю неправильно? Почему WCF настолько медленный?
Есть ли способ ускорить этот код?
Спасибо заранее.
EDIT:
Я немного изменил тест. Контракт одинаков.
Первый тест выглядит следующим образом (Wcf test):
class Program
{
private const int Iterations = 5000;
static void Main(string[] args)
{
var address = "net.pipe://localhost/test";
var host = new ServiceHost(typeof(Remote));
host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
host.Open();
var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
Console.ReadKey();
host.Close();
}
private static void TestWcf(IRemote proxy, int iterations)
{
var start = DateTime.Now;
for (var i = 0; i < iterations; i++)
{
proxy.Hello("Sergey");
}
var stop = DateTime.Now;
Console.WriteLine("Wcf: {0} ms.", (stop - start).TotalMilliseconds);
}
}
Вот результаты:
Wcf: 2564 ms.
Wcf: 1026 ms.
Wcf: 986 ms.
Wcf: 990 ms.
Wcf: 992 ms.
Второй тест выглядит следующим образом (.Net Remoting test):
class Program
{
private const int Iterations = 5000;
static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("TestDomain");
var proxy =
(IRemote)
domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
Console.ReadKey();
}
private static void TestRemoting(IRemote proxy, int iterations)
{
var start = DateTime.Now;
for (var i = 0; i < iterations; i++)
{
proxy.Hello("Sergey");
}
var stop = DateTime.Now;
Console.WriteLine("Remoting: {0} ms.", (stop - start).TotalMilliseconds);
}
}
Вот результаты:
Remoting: 261 ms.
Remoting: 224 ms.
Remoting: 252 ms.
Remoting: 243 ms.
Remoting: 234 ms.
Как вы можете видеть,.Net Remoting работает быстрее. Тесты выполнялись за пределами отладчика.
Почему это так?
Ответы
Ответ 1
Отладчики не являются реальными мерами при попытке сравнить производительность, вот что я сделал и получил WCF Kicking Out Remoting с кольца;)
1) Также изменил ваш тест, чтобы запустить его из той же программы /exe
namespace ConsoleApplication6
{
[ServiceContract]
internal interface IRemote
{
[OperationContract]
string Hello(string name);
}
[ServiceBehavior]
internal class Remote : MarshalByRefObject, IRemote
{
public string Hello(string name)
{
return string.Format("Hello, {0}!", name);
}
}
class Program
{
private const int Iterations = 5000;
static void Main(string[] p)
{
TestWcf();
TestRemoting();
}
static void TestWcf()
{
var address = "net.pipe://localhost/test";
var host = new ServiceHost(typeof(Remote));
host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
host.Open();
var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
TestWcf(proxy, Iterations);
Console.WriteLine("WCF done");
host.Close();
}
private static void TestWcf(IRemote proxy, int iterations)
{
var start = DateTime.Now;
for (var i = 0; i < iterations; i++)
{
proxy.Hello("Sergey");
}
var stop = DateTime.Now;
Console.WriteLine("Wcf: {0} ms.", (stop - start).TotalMilliseconds);
}
static void TestRemoting()
{
var domain = AppDomain.CreateDomain("TestDomain");
var proxy =
(IRemote)
domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
TestRemoting(proxy, Iterations);
Console.WriteLine("Remoting done");
Console.ReadKey();
}
private static void TestRemoting(IRemote proxy, int iterations)
{
var start = DateTime.Now;
for (var i = 0; i < iterations; i++)
{
proxy.Hello("Sergey");
}
var stop = DateTime.Now;
Console.WriteLine("Remoting: {0} ms.", (stop - start).TotalMilliseconds);
}
}
}
2) Скомпилируйте его в режиме деблокирования и запустите его вне отладчика.
вот мой вывод
![enter image description here]()
Ответ 2
Если в дополнение к коду SSamra вы перемещаете создание своего хоста вне вашего теста WCF (поскольку, на мой взгляд, вы должны создавать только хост только один раз), вы можете получить еще более быстрые ответы:
static void Main(string[] args)
{
var address = "net.pipe://localhost/test";
host = new ServiceHost(typeof(Remote));
host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
host.Open();
proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));
TestWcf(Iterations);
TestRemoting(Iterations);
TestWcf(Iterations);
TestRemoting(Iterations);
TestWcf(Iterations);
TestRemoting(Iterations);
host.Close();
Console.ReadKey();
}
Ответы:
![enter image description here]()
Это показывает, что при такой настройке WCF в процессе значительно быстрее, чем .Net remoting!
Ответ 3
В статье MSDN, которую вы ссылаетесь в начале вашего вопроса, сравнивается Remoting с WCF NetNamedPipes как механизм IPC (что означает межпроцессное общение, а не внутрипроцессное общение). Ваш тестовый код сравнивает производительность для связи в рамках одного и того же процесса.
Я понимаю, что дизайнеры WCF поставили перед собой цель существенно избить все ранее существовавшие технологии удаленного доступа для производительности, во всех сценариях межсетевых и межсетевых процессов, но не обязательно в разных доменах в рамках одного и того же процесса. На самом деле, я думаю, что они слишком близки к производительности Remoting в междоменном сценарии, как и другие ответчики. Но вы не должны удивляться, если вы не получите прирост производительности от использования WCF в этом конкретном сценарии.
Не стоит сомневаться в превосходной производительности WCF для Inter-Process Communication.
Ответ 4
Wcf: 261,03 ms.
Wcf: 247,02 ms.
Wcf: 236,02 ms.
Wcf: 235,02 ms.
Wcf: 236,02 ms.
WCF NetNamedPipeBinding done. Avg : 243,02
Wcf: 508,05 ms.
Wcf: 467,05 ms.
Wcf: 484,05 ms.
Wcf: 458,05 ms.
Wcf: 458,05 ms.
WCF NetTcpBinding done. Avg : 475,05
Remoting: 35,00 ms.
Remoting: 58,01 ms.
Remoting: 35,00 ms.
Remoting: 35,00 ms.
Remoting: 34,00 ms.
Remoting done. Avg : 39,40