←back to thread

257 points keepamovin | 7 comments | | HN request time: 0s | source | bottom
Show context
zh3 ◴[] No.44349227[source]
Seared into my soul is the experience porting a linux pipe-based application to Windows, thinking it's all posix and given it's all in memory the performance will be more or less the same. The performance was hideous, even after we found that having pipes waiting for a connection more or less ground windows to a halt.

Some years later this got revisited due to needing to use the same thing under C# on Win10 and while it was better it was still a major embarrassment how big the performance gap was.

replies(6): >>44349822 #>>44349883 #>>44349995 #>>44352604 #>>44354110 #>>44356780 #
dataflow ◴[] No.44352604[source]
> The performance was hideous, even after we found that having pipes waiting for a connection more or less ground windows to a halt.

When you say the performance was hideous, are you referring to I/O after the pipe is already connected/open, or before? The former would he surprising, but the latter not - opening and closing a ton of pipes is not something you'd expect an OS to be optimized for - and it would be somewhat surprising if your use case requires the latter.

replies(1): >>44352936 #
1. zh3 ◴[] No.44352936[source]
Literally just having spare listening sockets, ready for incoming connections (and obv. not busy-waiting on them). Just reducing to the number actually in-use was the biggest speed-up - it was like Windows was busy-waiting internally for new connections (it wasn't a huge number either, something like 8 or 12).
replies(1): >>44353579 #
2. dataflow ◴[] No.44353579[source]
By "spare listening sockets" do you mean having threads on the server calling ConnectNamedPipe? A bit confused by your terminology since these aren't called listening sockets. (You're not referring to socket() or AF_UNIX, right?)

And yeah, that seems more or less what I expected. The implementation is probably optimized for repeated I/O on established connections, not repeated unestablished ones. Which would be similar to filesystem I/O on Windows in that way - it's optimized for I/O on open files (especially larger ones), not for repeatedly opening and closing files (especially small ones). It makes me wonder what kinds of use cases require repeated connections on named pipes.

If the performance is comparable to Linux's after the connection, then I think that's important to note - since that's what matters to a lot of applications.

replies(2): >>44353751 #>>44357906 #
3. zh3 ◴[] No.44353751[source]
Yes, it was indeed using ConnectNamedPipe - just had a look at the code (which I can't share) to refresh my memory. The main problem was traced to setup delays in WaitForSingleObject()/WaitForMultipleObjects(); we fixed it as above (once all sessions were connected there were no spares left, so no problems), actual throughput was noted as quite inferior to linux but more than enough for our application so we left it there.
replies(1): >>44354106 #
4. dataflow ◴[] No.44354106{3}[source]
Ah interesting, thanks for checking. Not entirely sure I understand where the waits were happening, but my guess here is that the way Microsoft intended listening to work is for a new pipe listener to be spawned (if desired) once an existing one connects to a client. That way you don't spawn 8 ahead of time, you spawn 1 and then count up to 8.

I would intuitively expect throughout (once all clients have connected) to be similar to on Linux, unless the Linux side uses syscalls like vmsplice() - but not sure, I've never tried benchmarking.

5. yndoendo ◴[] No.44357906[source]
Windows API is built on kludge of functionality, not performance. For example, GetPrivateProfileString [0] does exactly what you stated for files. Opens, parses a single key value, and closes. So much time and resources are wasted with the GetPrivateProfileXXXX APIs.

[0] https://learn.microsoft.com/en-us/windows/win32/api/winbase/...

replies(1): >>44358281 #
6. dataflow ◴[] No.44358281{3}[source]
This function is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry.

They literally provided the registry to solve this very problem from the days of 16-bit Windows. Holding it against them in 2025 when they have given you a perfectly good alternative for decades is rather ridiculous and is evidence for the exact opposite of what you intended.

replies(1): >>44383809 #
7. yndoendo ◴[] No.44383809{4}[source]
This functionality is still used in software after 16-bit. It is even used by Skyrim software developers when it was "mark for compatibility by Microsoft". There is a project that hacked around this bad API [0]. You are going off the documentation wording versus real-world usage. Anyone that plays Skyrim today or in the future is still being harmed by this bad API.

INI files are 100% different than the Registry. I rather have an configuration file over registry entries because the registry is just another kluge of bad design. Configuration files are text files that are well defined.

Example would be the registry settings to mark a URL that it needs to run in IE compatibility mode because the source use old IE features that are now obsolete and don't even work in Edge or a modern browser. It should of just been a simple string array.

[0] https://www.nexusmods.com/skyrimspecialedition/mods/18860