Normally within 3 Tier applications that leverage the NetTcpBinding behind a firewall within an intranet environment I prefer to switch off security altogether since this is a trusted network zone and performace should be maximised in this case. There are times when this environment may not be trusted in which case you will need to start tweeking the relevant WCF security settings. Understanding the performance ramifications when enabling security is very important in my opinion. I was recently interested in the ProtectionLevel security setting which can be set imperatively or declaratively... so I knocked up the following performace test to see what the different performace ramifications are for the three possible options relating to ProtectionLevel.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Net.Security;
using System.Diagnostics;
namespace ConsoleApplication1
{
//This is the minimum protection level that the binding must comply with.
[ServiceContract(ProtectionLevel = ProtectionLevel.None)]
public interface IConvertString
{
[OperationContract]
string ConvertString(string input);
}
// Simple service which reverses a string and returns the result
public class ConvertStringService : IConvertString
{
#region IConvertString Members
public string ConvertString(string input)
{
char[] chars = input.ToCharArray();
chars.Reverse<char>();
return chars.ToString();
}
#endregion
}
class Program
{
// Setup the Service host
private static ServiceHost StartServer<T>(string Uri, NetTcpBinding binding)
{
Uri uri = new Uri(Uri);
ServiceHost host = new ServiceHost(typeof(ConvertStringService));
host.AddServiceEndpoint(typeof(T), binding, uri);
host.Open();
Console.WriteLine("Service opened using NetTcpBinding with {0} protection level.", Enum.GetName(typeof(ProtectionLevel), binding.Security.Transport.ProtectionLevel));
return host;
}
// Create channel using NetTcp binding with Uri and execute performance test.
private static double RunPerformanceTestOnNetTcpBinding(NetTcpBinding binding, string endpointUri)
{
const int iterations = 300;
const string stringToConvert = "12";
Stopwatch watch = new Stopwatch();
watch.Start();
for (Int32 i = 0; i < iterations; i++)
{
ChannelFactory<IConvertString>.CreateChannel(binding,
new EndpointAddress(endpointUri))
.ConvertString(stringToConvert);
}
watch.Stop();
Console.WriteLine("ConvertString with ProtectionLevel {2} : {0} times; Time taken : {1} ",
iterations.ToString(),
watch.Elapsed.TotalSeconds.ToString(),
Enum.GetName(typeof(ProtectionLevel), binding.Security.Transport.ProtectionLevel));
return watch.Elapsed.TotalSeconds;
}
static void Main(string[] args)
{
string uri = "net.tcp://localhost:7000/IConvertString";
NetTcpBinding bindingNoEncryption = new NetTcpBinding();
bindingNoEncryption.Security.Mode = SecurityMode.Transport;
bindingNoEncryption.Security.Transport.ProtectionLevel = ProtectionLevel.None;
NetTcpBinding bindingWithSign = new NetTcpBinding();
bindingWithSign.Security.Mode = SecurityMode.Transport;
bindingWithSign.Security.Transport.ProtectionLevel = ProtectionLevel.Sign;
NetTcpBinding bindingWithEncryption = new NetTcpBinding();
bindingWithEncryption.Security.Mode = SecurityMode.Transport;
bindingWithEncryption.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
Console.WriteLine("Run performance test or press q to Quit...");
while (Console.ReadLine() != "q")
{
double noEncryptionTime;
double signTime;
double encryptionTime;
using (ServiceHost host = StartServer<IConvertString>(uri, bindingNoEncryption))
{
noEncryptionTime = RunPerformanceTestOnNetTcpBinding(bindingNoEncryption, uri);
host.Close();
}
using (ServiceHost host = StartServer<IConvertString>(uri, bindingWithSign))
{
signTime = RunPerformanceTestOnNetTcpBinding(bindingWithSign, uri);
host.Close();
}
using (ServiceHost host = StartServer<IConvertString>(uri, bindingWithEncryption))
{
encryptionTime = RunPerformanceTestOnNetTcpBinding(bindingWithEncryption, uri);
host.Close();
}
Console.WriteLine("Run performance test again or press 'q' to Quit...");
}
}
}
}
The results from my performance test were interesting.... see below:
As you can see from the above tests the when using Transport security with the NetTcpBinding ProtectionLevel Sign performance is not much different to EncryptAndSign, although there is a definite performance increase when using Protection Level None.