ServicePointManager.DefaultConnectionLimit == 2? Depends…
“Depends” is my favorite answer when teaching .NET-related courses, because behind this simple word lies the implementation of the CLR and BCL, which sometimes lead us to answers we didn’t expect.
For example, take the question in the topic: according to MSDN, the default value of System.Net.ServicePointManager.DefaultConnectionLimit is 2. So I wrote some code that tries to open a lot of connections from a console application to a WCF service, and to my amaze, I was able to send dozens of requests at a time, without hitting the two connection limit.
So I used my debugging skills, and found out that although the default value for the connection limit was 2, the ServicePoint.ConnectionLimit for my connection was set to 2147483647 – I didn’t expect that!
If you look at the MSDN page for ServicePoint.ConnectionLimit you can clearly see that it says: “The value of the ConnectionLimit property is set to the value of the ServicePointManager.DefaultConnectionLimit property when the ServicePoint object is created”. If the DefaultConnectionLimit has the default value of 2, that should have also set the ConnectionLimit value to 2, or am I wrong? I’m probably wrong thinking it’s that obvious.
Therefore, I went to reflector to see what I was doing wrong, and after searching around a bit, I found the following implementation in the ServicePoint.ConnectionLimit get property:
public int get_ConnectionLimit()
{
if ((!this.m_UserChangedLimit && (this.m_IPAddressInfoList == null))
&& (this.m_HostLoopbackGuess == TriState.Unspecified))
{
lock (this)
{
if ((!this.m_UserChangedLimit && (this.m_IPAddressInfoList ==
null)) && (this.m_HostLoopbackGuess == TriState.Unspecified))
{
IPAddress address = null;
if (IPAddress.TryParse(this.m_Host, out address))
{
this.m_HostLoopbackGuess =
IsAddressListLoopback(new IPAddress[] { address })
? TriState.True : TriState.False;
}
else
{
this.m_HostLoopbackGuess =
NclUtilities.GuessWhetherHostIsLoopback(this.m_Host) ?
TriState.True : TriState.False;
}
}
}
}
if (!this.m_UserChangedLimit &&
!((this.m_IPAddressInfoList == null) ?
(this.m_HostLoopbackGuess != TriState.True) :
!this.m_IPAddressesAreLoopback))
{
return 0x7fffffff;
}
return this.m_ConnectionLimit;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
If you look at the above code, you will notice something that pops at you right away – loopback.
Apparently the property checks if you are trying to access your own machine before deciding which limit to use. In my case I was connecting to my machine, and I ended up getting the value of 0x7fffffff which translates to 2147483647 – which is what I saw while debugging.
I went and made a quick change, found an available server, installed my testing service in it, changed the address, and voila – the ServicePoint.ConnectionLimit returned 2, and I could see that only two connections were executing at any given time.
Now let’s go back to the question I asked and ask it again:
Is ServicePointManager.DefaultConnectionLimit == 2? It depends:
1. If you are calling a remote service, then yes, it will be 2 by default
2. If you are calling to your local machine, then no, the default will be Int32.MaxValue
For best performance, the recommendation is to set the ServicePointManager.DefaultConnectionLimit to 12 times the number of cores in your client machine (for example, I have an 8 core machine, therefore 12*8=96 connections).
“Depends”, I love that answer.
By the way, next week we’re having our DevDays at Sela, and I’m going to give an advanced course in WCF. If you thought this anecdote was interesting, come and learn more about some hidden features and settings of WCF. I promise lots of fun and a lot of “it depends” answers.