Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow Ping Class #102445

Open
aliajboy opened this issue May 20, 2024 · 4 comments
Open

Slow Ping Class #102445

aliajboy opened this issue May 20, 2024 · 4 comments
Labels
area-System.Net untriaged New issue has not been triaged by the area owner

Comments

@aliajboy
Copy link

aliajboy commented May 20, 2024

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

  • i3 6100
  • Dotnet 8.0.5
  • VS 17.9.7
  • Windows 10 x64
  • ASP.Net Core MVC

Other information

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

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 20, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 20, 2024
@huoyaoyuan huoyaoyuan added area-System.Net and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels May 20, 2024
Copy link
Contributor

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

@huoyaoyuan
Copy link
Member

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

@aliajboy
Copy link
Author

@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
Copy link
Member

wfurt commented May 20, 2024

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

private unsafe int SendEcho(IPAddress address, byte[] buffer, int timeout, PingOptions? options, bool isAsync)
{
Interop.IpHlpApi.IP_OPTION_INFORMATION ipOptions = new Interop.IpHlpApi.IP_OPTION_INFORMATION(options);
if (!_ipv6)
{
return (int)Interop.IpHlpApi.IcmpSendEcho2(
_handlePingV4!,
GetWaitHandle(isAsync),
IntPtr.Zero,
IntPtr.Zero,
#pragma warning disable CS0618 // Address is marked obsolete
(uint)address.Address,
#pragma warning restore CS0618
_requestBuffer!,
(ushort)buffer.Length,
ref ipOptions,
_replyBuffer!,
MaxUdpPacket,
(uint)timeout);
}

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Net untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants