Live data from Hacker News

The Windows malloc() implementation from MSVCRT is slow

erikmcclure.com

121–130 of 187 posts

Re: The Windows malloc() implementation from MSVCRT is slow

#121

> I was taught that to allocate memory was to summon death itself to ruin your performance. A single call to malloc() during any frame is likely to render your game unplayable. Any sort of allocations that needed to happen with any regularity required writing a custom, purpose-built allocator, usually either a fixed-size block allocator using a freelist, or a greedy allocator freed after the level ended. Where do peo…

I'm a sometimes real-time programmer (not games - sound, video and cable/satellite crypto) - malloc(), even in linux is an anathema to real-time coding (because deep in the malloc libraries are mutexes that can cause priority inversion) - if you want to avoid the sorts of heisenbugs that occur once a week and cause weird sound burbles you don't malloc on the fly - instead you pre-alloc from non-real-time code and run your own buffer lists

Re: The Windows malloc() implementation from MSVCRT is slow

#122
post #104
post #95

Earlier quoted context omitted.

I don't see a reason for the stdlib to be considered in a different way from the base language is all I'm saying. For most C programmers, the distinction between the stdlib and the base language isn't even a consideration. Thinking most software doesn't heavily rely on malloc (and the rest of the stdlib) being fast is stupid. Even on hardware without a multiplier you'd do a shift-based version, with log_2(max_value)…

C and C++ are some of the few languages where the spec goes out of its way to not depend on an allocator, for good reason, and this is well after you've accounted for the majority of the code that, hopefully, doesn't need to do memory allocation at all. The fact that many programmers don't care is an indication that most code in most C or C++ software is not written with performance in mind. And that's (sometimes) fi…

The fact that you should avoid allocation when possible has absolutely nothing to do with how fast allocation should be when you need it. And code not written with performance in mind should still be as fast as reasonably possible by default.

I would assume that quite a few people actually trying to write fast code would just assume that malloc, being provided to you by your OS, would be in the best position to know how to be fast. Certainly microsoft has the resources to optimize the two most frequently invoked functions in most C/C++ codebases, at least more than you yourself would.

MSVCRT being stuck with the current extremely slow thing, even if there are truly good reasonable reasons, is still a horrible situation to be in.

Re: The Windows malloc() implementation from MSVCRT is slow

#123

Earlier quoted context omitted.

Note that Windows has HeapAlloc and HeapFree, which provide all the functionality to trivially implement malloc and free. The C runtime is doing exactly that, except it adds a bit of bookkeeping on top of it IIRC. And in debug builds it adds support for tracking allocations.

VirtualAlloc is a better base for a custom memory allocator. It's closer to mmap + mprotect in functionality. There's also CoTaskMemAlloc (aka IMalloc::Alloc). And COM automation has a bunch of methods which allocate memory for dynamically sized data, which could be abused for memory allocation - SafeArrayCreate, SysAllocString.

It sounds like they've invented 15 different ways to allocate memory rather than have malloc. What did they do that for?

(Not to say malloc is a perfect API, it’s definitely oversimplified, but they probably didn’t solve any of its problems.)

Re: The Windows malloc() implementation from MSVCRT is slow

#124

> I was taught that to allocate memory was to summon death itself to ruin your performance. A single call to malloc() during any frame is likely to render your game unplayable. Any sort of allocations that needed to happen with any regularity required writing a custom, purpose-built allocator, usually either a fixed-size block allocator using a freelist, or a greedy allocator freed after the level ended. Where do peo…

I'm a sometimes real-time programmer (not games - sound, video and cable/satellite crypto) - malloc(), even in linux is an anathema to real-time coding (because deep in the malloc libraries are mutexes that can cause priority inversion) - if you want to avoid the sorts of heisenbugs that occur once a week and cause weird sound burbles you don't malloc on the fly - instead you pre-alloc from non-real-time code and run…

Mutexes shouldn't be able to cause priority inversion, there's enough info there to resolve the inversion unless the scheduler doesn't care to - i.e. you know the priority of every thread waiting on it. I guess I don’t know how the Linux scheduler works though.

But it's not safe to do anything with unbounded time on a realtime thread, and malloc takes unbounded time. You should also mlock() any large pieces of memory you're using, or at least touch them first, to avoid swapins.

Re: The Windows malloc() implementation from MSVCRT is slow

#125

Earlier quoted context omitted.

I think the smart move would have been to make an official port of bash...

Some experimentation in that space is probably a good thing. Bash is familiar, but it's far from perfect. In terms of executing programs, it gets the critical functionality down pretty well; readline-based editing, variables, aliases, pipes, IO redirects, background process management, etc. In terms of being a programming language, I always regret when I use it. I recently had a minor heart attack when I realized tha…

> The various shells running under the multiplexer overwrite each other's history.

GitHub seems to have umpteen different variations on "store the shell history in a SQLite database": https://github.com/thenewwazoo/bash-history-sqlite https://github.com/trengrj/recent https://github.com/andmarios/bashistdb https://github.com/digitalist/bash_database_history https://github.com/quitesimpleorg/hs9001 https://github.com/hinzundcode/termmon https://github.com/fvichot/hisql https://github.com/bcsgh/bash_history_db https://github.com/jcsalterego/historian

This seems a popular enough idea, I wonder why it hasn't just added to Readline/libedit/etc? (Would the maintainers of those packages agree to add such an idea to them?)

> The shell history is specific to the machine that the shell is running on, not the machine that the terminal is running on

Once you've got the idea of shell history in sqlite – why not have a (per-user) daemon which exposes that history, some RPC protocol over a Unix domain socket, with the name of the socket in an environment variable? Then you can forward that socket over SSH? Again, something that could go in readline/libedit/etc, if their maintainers could agree to it.

> The terminal multiplexer can't give the terminal emulator its scrollback buffer.

Someone needs to come up with a new protocol here, instead of just pretending we are all still using physical VT series terminals over serial lines? The biggest problem with introducing any such protocol would be getting everyone to agree to adopt it. One could make patches for a few different terminal multiplexers and emulators, but would the maintainers accept them?

Re: The Windows malloc() implementation from MSVCRT is slow

#126
post #99

Earlier quoted context omitted.

Glibc is major source of "binary from X years ago doesn't work" in my experience, to the point that if I want to run stuff older than let's say 5 years I start by getting a docker container - or a specially taylored set of libs starting with dynamic linker itself. Somehow proprietary OpenGL drivers still worked, it was glibc related files that caused crashes. Thanks to symbol versioning I never know if a binary will…

For example: https://github.com/microsoft/vscode-remote-release/issues/10...

This is the opposite problem of what's being talked about. Binaries built against old versions of glibc should run just fine against newer versions. This is about a binary built against a newer version of glibc that doesn't run on an older one. This is common, and super annoying. There are ways to build to eliminate this problem, but they all feel like hacks, or involve a lot of extra work.

(Hacks such as https://github.com/wheybags/glibc_version_header -- which apparently does work very well, but still feels like an annoying hoop that should be unnecessary to jump through. I wish glibc's shipped headers actually could support this out of the box so you could set a preprocessor define like `-DGLIBC_TARGET_ABI=2.12` and it would just work.)

Re: The Windows malloc() implementation from MSVCRT is slow

#127

Earlier quoted context omitted.

There's also UCRT, which ships with the OS since Windows 10. The logic of this rant was a real head-scratcher. If you must blame one side, it's LLVM. Fragmentation of C runtimes is annoying but inescapable. Glibc for example isn't any better.

> Fragmentation of C runtimes is annoying but inescapable. Glibc for example isn't any better. Glibc very much is better. There cannot be more than a single version of a (tightly coupled) ld.so+libc.so pair in a given address space any more than there can be more than a single KERNEL32 version in a given address space, and given that some system services are exclusively accessible via dynamic linking (accelerated gra…

> Actually building a backwards-compatible binary that references old symbol versions is a gigantic pain: you either have to use a whole old environment, apply symbol versioning hacks on top of a new one and pray the resulting chimera works, or patch antique Glibc sources for new compilers and build a cross toolchain.

This is the example I gave downthread. It's an everyday problem for a lot of developers targeting Linux, whereas targeting decades-old Windows versions is a breeze.

Glibc isn't better, it just has different problems.

Re: The Windows malloc() implementation from MSVCRT is slow

#128
post #46

Earlier quoted context omitted.

There's also UCRT, which ships with the OS since Windows 10. The logic of this rant was a real head-scratcher. If you must blame one side, it's LLVM. Fragmentation of C runtimes is annoying but inescapable. Glibc for example isn't any better.

The UCRT has even been present since Windows 7, if users keep up with updates. Or if applications bundle the UCRT installer with their own.

> Or if applications bundle the UCRT installer with their own.

But the UCRT is proprietary, so there are often legal issues with doing so.

Re: The Windows malloc() implementation from MSVCRT is slow

#129

Earlier quoted context omitted.

Could you elaborate why Glibc isn't any better? I remember some funny problems with Glibc, like, 20 years ago, but it's been invisible to me (as a user) since then. You get a new Glibc, old binaries still work, it's fine.

Just like with Windows the challenges affect developers rather than users. > You get a new Glibc, old binaries still work, it's fine. Indeed, but when you need to build for an older glibc it's not so simple. This is a common use case, since e.g. AWS's environments are on glibc 2.26. Ideally you'd like to build for all targets, including older systems, from a single, modern environment (this is trivial in Windows) --…

> Ideally you'd like to build for all targets, including older systems, from a single, modern environment (this is trivial in Windows)

https://github.com/sjmulder/netwake does what you're talking about, but it does a lot of gymnastics to make it work, and it also needs to use MinGW rather than MSVC for that to be the case.

Re: The Windows malloc() implementation from MSVCRT is slow

#130

Earlier quoted context omitted.

But if you're using it for yourself you wouldn't want to put it in system32.

There was a looong period of time where a lot of developers felt entirely free to drop whatever they wanted into c:\Windows, System, System32, whatever. It's a big part of what led to windows getting a reputation for being poorly behaved/crashy/slow over time [leading to a lot of "have you tried reinstalling windows?" recommendations]

Yes but I think that's separate from a newer installer using one of these newer runtimes.
Post reply on HN