How do we improve the performance of conhost processes when we ping a bunch of servers?

A customer had a program that launches many instances of the ping program in order to check the availability of a large number of servers. They found that each copy of ping comes with a copy of conhost.exe, and all these conhost processes degrade system performance by a factor of four. They were looking for guidance on how they could improve the performance of the conhost process.

Well, the best way to avoid performance issues with conhost is to stop using conhost.

It sounds like the customer was launching the ping program and then either parsing the output or studying the exit code in order to determine whether the server was up. Instead, they could use the System.Net.Network­Information.Ping class (if programming in C#) or the Icmp­Send­Echo function (if programming in C/C++). Not only is this more efficient, you get detailed status results which will help you decide which server your program should use.

(Both functions report the ping time in milliseconds because the speed of light is unlikely to improve.)

Comments (17)
  1. Klimax says:

    Maybe they were of UNIX background. Sounds like imported “bright” idea from there…

    1. Yukkuri says:

      The unix approach is stellar up to a point… that point being where performance is more important than the time spent creating the solution :)

      Sounds like here whoever this was got out of their depth… doing the pinging yourself is an immediately obvious choice if you have a reasonable grasp of programming.

      1. Cesar says:

        On Unix, there’s no conhost process, only the ping process itself, and you don’t even have to allocate a TTY for it, so it’s very lightweight. And as someone else noted, it’s traditionally the only way, as only root could use raw sockets, and the ping executable is setuid root (or, on more modern systems, not setuid root but with raw socket capabilities).

        You can nowadays also use IPPROTO_ICMP to send ICMP ECHO packets directly (similar to the Windows solution), but it’s a very recent alternative which is not available on all Unix systems.

        So, I agree: the programmer probably had a Unix background. On Unix, it’s a perfectly fine solution, and for many systems the only one.

        1. Yukkuri says:

          Only root could use raw sockets? I suppose that stems from times when computers were rare and shared and people hadn’t yet given up on the idea of keeping a network running by controlling the sender rather than hardening the receiver…

  2. I would have thought that user-level applications would need special permissions to send ICMP packets on Windows like they do on Linux (ping(1) is setuid root there), but apparently not. Does that mean user code has permissions to write raw packets, or is IcmpSendEcho() implemented using some syscall different from what WSASendTo() uses that specifically writes ICMP packets?

    1. Joshua says:

      It turns out the raw packet request won’t let you forge packets from other IP addresses or TCP packets at all so its mostly harmless.

    2. Ivan K says:

      Yeah, I wrote a program way back when that did ICMP pings and also some UDP stuff with raw sockets. When XP SP2 came out it was realised that without admin privileges either or some or none of that succeeded.

  3. alegr1 says:

    Somebody was too lazy to read CreateProcess flags.

  4. poizan42 says:

    For anyone wondering, the required flag is DETACHED_PROCESS. Now this will result in no console being allocated for the process at all (just like if the subsystem field in the PE was win32). But a program that’s okay with having its standard handles redirected yet still expecting a console to be allocated seems highly unlikely.

    Sadly the System.Diagnostics.Process class does not expose this flag, and lacks any way of extending it with supporting more flags, so you have to bypass it completely and use P/Invoke yourself.

    1. poizan42 says:

      … So I wrote this comment as a reply to another comment that stated that they should have read the documentation for CreateProcess, but apparently that other comment was deleted while I wrote my comment, and the way the blog software choose to handle that seems to have been to make my comment a top-level comment…

  5. poizan42 says:

    I know from the discussions over at that the console team are working on a larger restructuring/refactoring of the whole console system. I hope they can also change it such that no conhost process is started when a process is created with CREATE_NO_WINDOW since AFAICT all the bookkeeping of the console handle attached to the invisible console could be done internally as long as it doesn’t need to interact with the desktop.

  6. smf says:

    Ping is a poor indication of server availability, with both false positives and false negatives. It can only tell you that something is responding, not that it is the correct server or the server is processing requests. ICMP can be dropped but the server may be fine

    1. Agreed, it’s better to use deep health checks that go into the application layer, e.g. by performing a GET of a URI like /status for an HTTP application. If the host is up but the web server is not listening on its port or is not responding to requests for any reason, then pings will succeed but the deep health checks will fail.

      The status servlet can even do deeper application-specific health checks and return a 5xx error instead of 200 if it knows it can’t successfully serve requests for any reason. E.g. maybe its disks are reporting I/O errors or a dependent service is unavailable.

      1. Zan Lynx' says:

        That approach is great.

        Once you’ve found the few closest servers via ping.

        There was some game browser app that took your approach to checking the server list. All 1200+ servers. At over 4,000 bytes per server check. Just loading it would knock my friends out of the games they were playing.

        1. Patrick says:

          ICMP is frequently down-prioritized and/or rate limited, so it’s not a good universal solution.

        2. The right health check to use depends on the client’s purpose. For something like a game querying 1200 servers to find the closest server, an ICMP ping makes a lot more sense. For something like a load balancer with multiple redundant web servers behind it, you want the LB doing deeper health checks so that it can remove unhealthy hosts from service.

  7. anai says:

    This is one to stir the memory, I remember using the, then, undocumented IcmpSendEcho from ICMP.dll in the last century.

    Lots written on why PING is a poor tool, but if you get a response, you know that there is IP connectivity between you and the host with that IP, and that the host with that IP is powered.

    Does it mean your server is fully functioning and that your services are responding? no…

Comments are closed.

Skip to main content