dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.55k stars 4.54k forks source link

Slow Ping Class #102445

Open aliajboy opened 1 month ago

aliajboy commented 1 month ago

Description

Describe the bug

I want to ping about 180 IPs that most of them, say about 175 of them are disconnected from local network and respond timeout. I know about this and I set timeout in Ping Command to 10ms so It shouldn't take a lot of time! BUT It takes 110 seconds to complete that is about 600ms. I tested async/await and without that, I used foreach and await Task.WhenAll but non of them seem to work, It is really weird. when I have them connected, I can say that this process takes about 1 sec to complete! I assume that this timeout setting in Ping command is just Ridiculous and doesn't do a thing. If this works, assume that all the IPs are dead, It should take 1.8 seconds to complete.

one of my codes:

            string data = "aaaaaaaaaaaaaaaa";
            byte[] byteBuffer = Encoding.ASCII.GetBytes(data);
            var list = new List<Task<PingReply>>();
            foreach (var item in model)
            {
                list.Add(new Ping().SendPingAsync(item.DevIPWIFI,10,byteBuffer));  // no await here
            }
            var replies = await Task.WhenAll(list);

the other one:

            foreach (var item in model)
            {
                PingReply reply = new Ping().Send(item.DevIPWIFI,10);
            }

and tested this one either: PingReply reply = await new Ping().SendPingAsync(item.DevIPWIFI,10); // And this one with await

After I saw the delay, I tested the timeout specially to see how it react, but it doesn't react like it supposed to do.

I have to mention that if the devices are connected and have ping, all 180 IPs will respond in less than a second!

Reproduction Steps

make a list of 180 IPs that are disconnected and respond with timeout. Use SendPingAsync() or Send() Method to get respond.

Expected behavior

timeout as I expected.

Actual behavior

won't timeout as I mentioned. no matter if you put 1ms or 100ms

Regression?

No response

Known Workarounds

No response

Configuration

Other information

I asked SDK team and stackoverflow, but they send me to dotnet runtime team.

dotnet-policy-service[bot] commented 1 month ago

Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.

huoyaoyuan commented 1 month ago

It sounds like Ping is not respecting timeout. You can verify this by measuring one request to one known disconnected destination.

aliajboy commented 1 month ago

@huoyaoyuan as I mention in the Question itself, I have tested and confirmed that it doesn't respect the timeout. I even test in debug mode and saw that the request will respond in range of 250-500ms

wfurt commented 1 month ago

That seems to be problem with underlying Windows API. We pass timeout to it and it works as expected for larger value (1s+) but it is not that precise for vary short timouts

https://github.com/dotnet/runtime/blob/24562bcabefaea5e03c74d01e4df8fc7c112a13a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Windows.cs#L164-L183

The async option may be best IMHO as one should not need to wait for the response. But it also allocates wait handle and does what async does. And that will cost something regardless.

The easy workaround could probably be Task.WhenAny in cycle or something like Task.WaitAll(list.ToArray(), TimeSpan.FromMilliseconds(10)); and mark unfinished tasks as timeout.

liveans commented 2 days ago

Triage: Not critical for 9.0, moving to the future.