问题
Before i get started... this is NOT FOR PRODUCTION; The question really only came about while making a test application. Myself and another developer were poking around with why .net was performing this poorly this way. It may not be .net at all, it could be the OS, I hope someone can shed some light on topic:
My test application was created to handle hundreds of connections from our production app which connects to hundreds of devices via TCP only because its easier to simulate 500-700 PCs then then have 500-700 physical machines stacked up in my office running some port software.
I created a sample chunk that you can copy/paste into your test VS if you are interested in finding a solution. Its quite simple and easy to reproduce.
Issues:
- As each port is opened, it takes longer and longer for the next port to open.
- The CPU is quite intense just to create one port after it has created several hundred
Notes:
- Thread count is normal... very low (16ish threads in task manager)
- Handle count is also normal as it adds each socket.
- Memory usage also looks normal
- Used reflector to look at the .net libs to see what Start() was doing, and it looks like normal socket calls.
Sample Code:
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
namespace SocketPerformanceTest
{
class Program
{
static void Main(string[] args)
{
const int socketToOpen = 500;
const int socketStartingPoint = 45000;
var sw = new Stopwatch();
for (var i = 0; i < socketToOpen; i++)
{
var thisPort = socketStartingPoint + i;
try
{
var listener = new TcpListener(IPAddress.Any, thisPort);
sw.Restart();
listener.Start();
sw.Stop();
Console.WriteLine("Started Port {0} in {1}", thisPort, sw.Elapsed);
}
catch{}
}
}
}
}
Console Output:
When the test application first starts, notice that each port slowly rises in execution time. The Stopwatch wraps the Start() method:
Started Port 45000 in 00:00:00.0086440
Started Port 45001 in 00:00:00.0131427
Started Port 45002 in 00:00:00.0125916
Started Port 45003 in 00:00:00.0140987
Started Port 45004 in 00:00:00.0214274
Started Port 45005 in 00:00:00.0166746
Started Port 45006 in 00:00:00.0178583
Started Port 45007 in 00:00:00.0203611
Started Port 45008 in 00:00:00.0187707
Started Port 45009 in 00:00:00.0209386
Started Port 45010 in 00:00:00.0229595
Started Port 45011 in 00:00:00.0298687
Started Port 45012 in 00:00:00.0331132
Started Port 45013 in 00:00:00.0312815
Started Port 45014 in 00:00:00.0295004
Started Port 45015 in 00:00:00.0312391
Started Port 45016 in 00:00:00.0326538
Started Port 45017 in 00:00:00.0329316
Started Port 45018 in 00:00:00.0330471
Started Port 45019 in 00:00:00.0353324
Started Port 45020 in 00:00:00.0391780
Started Port 45021 in 00:00:00.0405106
Started Port 45022 in 00:00:00.0391909
Started Port 45023 in 00:00:00.0410726
Started Port 45024 in 00:00:00.0519416
After about 400 ports are opened, notice how long it takes for each port to start. 1-2 seconds? CPU is also quite high for this operation:
Started Port 45399 in 00:00:01.3031324
Started Port 45400 in 00:00:01.2686192
Started Port 45401 in 00:00:01.2367192
Started Port 45402 in 00:00:01.3912566
Started Port 45403 in 00:00:01.2710675
Started Port 45404 in 00:00:01.2500153
Started Port 45405 in 00:00:01.2685378
Started Port 45406 in 00:00:01.3358896
Started Port 45407 in 00:00:01.2972177
Started Port 45408 in 00:00:01.3002466
Started Port 45409 in 00:00:01.4087936
Started Port 45410 in 00:00:01.5042491
Started Port 45411 in 00:00:01.2869177
Started Port 45412 in 00:00:01.3284299
Started Port 45413 in 00:00:01.3202311
Started Port 45414 in 00:00:01.4406063
Started Port 45415 in 00:00:01.3534663
Started Port 45416 in 00:00:01.7562387
Started Port 45417 in 00:00:01.5572173
Started Port 45418 in 00:00:01.4617214
Started Port 45419 in 00:00:02.1260768
Started Port 45420 in 00:00:01.6841706
Started Port 45421 in 00:00:01.7514512
Started Port 45422 in 00:00:01.5182234
Questions:
- Why does each port take longer to open then the last?
- Why does the CPU get higher and higher
- Am I doing something wrong? Is there a more efficient way to open a socket and listen for connections?
- Is this an OS issue, or a .net issue? I tested this on windows 7, do you think it will be different if I tested it on a Server OS? I believe the kernel with 2008 R2 and Win7 SP'ed are the same, so not sure if that matters.
Hardware:
- Win7 x64 Ultimate, 8 GB ram, I7, SSD, etc etc
It is not critical for me to find a solution for this, but it would be nice. I would like to have this simulator app start up, and listen to 500-700 unique TCP ports in a reasonable period of time. If there is a better way, please let me know... I am very interested on what is going on or alternative options.
Thanks!
Update 1
Tested it on a Raspberry Pi device which has hardly any CPU/Memory, and it was nearly instant. Others said it was instant in the comments.. and one said they saw the same thing. I also tested on a different PC, same issue I have. Disabled Firewall, AV, etc. I am really curious to why this is happening.
来源:https://stackoverflow.com/questions/14249739/tcplistener-performance-issues-with-start-after-hundreds-of-ports-open