Skip to content

Unnecessary IOCP wake-ups. #288

Description

@MarekKnapek

Hi, I was invited to participate in corosio review process. I noticed some inefficiency in IOCP usage.

Steps to reproduce:

  • Get a Windows machine.
  • Get corosio from this repository.
  • Somehow figure out how to build corosio. It is not easy as "just" a double-clicking on a Visual Studio solution project file, or "running" the default CMake file from command line. I ended up manually modifying the CMake file to include capy dependency.
  • Run the corosio_example_hash_server example porject.
  • There is a server being launched, it is listening for clients, waiting for them to connect, or whatnot.
  • The server is using a IOCP technology from Windows (basically epoll).
  • So far so good.
  • But. The server is sleeping on the IOCP with a 500 ms timeout.

This is not great. This means that if there is no events being posted to the IOCP for long periods of time, the waiting process wakes up regardless. Only to check some internal state and go back to the sleep again waiting for more IOCP events. This is wasteful. This adds unnecessary additional pressure to the OS kernel scheduler waking up the process and running it only to do "almost nothing". This brings the memory pages of the server app into working set, possibly reducing available amount of RAM usable for other task that are actually doing something useful. Not to mention possible swap activity.

Why is the reason waking up the server thread periodically? To check some internal state and act according to it? The server app should consume 0.00 % of CPU if there are no clients. Absolutely zero. If you really need to check some internal state and do something based on its value - then there is better solution than waking up twice every second. Post an event to the IOCP at the moment the internal state is being changed (right after the change). This will wake up the server process only when there is actually some work to be done. There is PostQueuedCompletionStatus Windows function for this purpose. It can carry two pointers and one integer of arbitrary payload. One is of type LPOVERLAPPED but in reality it is a pointer that does not need to point to any overlapped structure. Second is of type ULONG_PTR, basically uintptr_t. Third is of type DWORD, basically unsinged 32bit integer. Please make use of these three variables. Windows does not care about where they are poiting to, they can be arbitrary values.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions