Live data from Hacker News

The Windows malloc() implementation from MSVCRT is slow

erikmcclure.com

91–100 of 187 posts

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

#91
post #64
post #25

Earlier quoted context omitted.

This misses the point of my comment. When you put faith in malloc, you're putting hope in a lot of heuristics that may or may not degenerate for your particular workload. Windows is an outlier with how bad it is, but that should largely be irrelevant because the code should have already been insulated from the system allocator anyway. An over-dependence on malloc is one of the first places I look when optimizing old…

Except that I'd guess that there is no "good" case in the case for MSVCRT's malloc. You shouldn't assume malloc is free, but you should also be able to assume it won't be horrifyingly slow. Just as much as you should be able to rely on "x*y" not compiling to an addition loop over 0..y (which might indeed be very fast when y is 0). Yes, this unfortunately isn't the reality MSVCRT is in, but it is quite a reasonable ex…

It's unreasonable to assume that an stdlib must be designed around performance to any capacity. For most software, the priorities for the stdlib are 1) existing, 2) being bug/vulnerability free, and likely, in the Windows case given Microsoft's tradition, 3) being functionally identical to the version they shipped originally. Linux and macOS have much more flexibility to choose a different set of priorities (the former, through ecosystem competition and the latter through a willingness to break applications and a dependence on malloc for objc), so it's not at all a fair comparison. The fact that malloc doesn't return null all the time is a miracle enough for many embedded platforms, for example, so it's not exclusively a Windows concern. Environments emphasizing security in particular might be even slower.

Multiplication is not a great argument... There's a long history of hardware that doesn't have multipliers. Would I complain about that hardware being bad? No, because I'd take a step back and ask what their priorities were and accept that different hardware has different priorities so I should be prepared to not depend on them. Same thing with standard libraries. You can't always assume the default allocator smiles kindly on your application.

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

#92
post #14

If you're depending on the performance of malloc, you're either using the language incorrectly or using the wrong language. There is no such thing as a general purpose anything when you care about performance, there's only good enough. If you are 1) determined to stick with malloc and 2) want something predictable and better, then you are necessarily on the market for one of the alternatives to the system malloc anyw…

The whole point of the article, though, was that the system malloc was good enough on Linux and Darwin.

There isn't really a "system malloc on Linux". Many distributions come with the GNU allocator based on ptmalloc2, but there is no particular reason that a distro could not come out of the box with any other allocator. The world's most widespread Linux distribution uses LLVM's Scudo allocator. Alpine Linux comes with musl's (unbelievably slow) allocator, although it is possible to rebuild it with mimalloc.

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

#93
post #20

Well... Who told you to link to MSVCRT (the one in System32)? Not Microsoft that's for sure. New software is supposed to link to the Visual Studio C runtime it was compiled with and then ship that library alongside the application itself. Even if you don't compile with VS you can distribute the runtime library (freely downloadable from some page on microsoft.com). Ostensibly, that library contains an efficient malloc…

Isn’t every (release-mode) Microsoft CRT malloc a thin wrapper around KERNEL32!HeapAlloc (thus eventually NTDLL!RtlAllocateHeap)? CRTDLL did it, MSVCRT did it, UCRTBASE still seems to be doing it.

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

#94

Earlier quoted context omitted.

there's a weird licensing thing for the VC runtime where you can't redistribute the dll alongside your code unless you have a special license. instead, you have to install it as an MSI. I have no idea why they created that restriction. I even work for MS and it baffles me.

At one point MS was very keen for people to use MSI's rather than building custom installers that jam things into system32. Perhaps that was why.

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

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

#95
post #91
post #64

Earlier quoted context omitted.

Except that I'd guess that there is no "good" case in the case for MSVCRT's malloc. You shouldn't assume malloc is free, but you should also be able to assume it won't be horrifyingly slow. Just as much as you should be able to rely on "x*y" not compiling to an addition loop over 0..y (which might indeed be very fast when y is 0). Yes, this unfortunately isn't the reality MSVCRT is in, but it is quite a reasonable ex…

It's unreasonable to assume that an stdlib must be designed around performance to any capacity. For most software, the priorities for the stdlib are 1) existing, 2) being bug/vulnerability free, and likely, in the Windows case given Microsoft's tradition, 3) being functionally identical to the version they shipped originally. Linux and macOS have much more flexibility to choose a different set of priorities (the form…

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) iterations. What's unreasonable is "for (int i = 0; i < y; i++) res+= x;". If there truly were no way to do a shift, then, sure, I'd accept the loop; but I definitely would be pretty mad at a compiler if it generated a loop for multiplication on x86_64. And I think it's reasonable to be mad at the stdlib being purposefully outdated too (even if there is a (bad) reason for it).

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

#96

Earlier quoted context omitted.

(I work for MS, though in core Azure rather than Office or Windows.) I think that PowerShell story was how old MS worked, back in the days of stack ranking, hatred of Linux and the Longhorn fiasco. things inside the company are a lot more functional now. I saw internal politics drama at my first position, but once I moved everything was chill, and experimentation and contributing across team boundaries was actively e…

any idea what the hell is going on with Teams? why can't i simply scroll up in my own conversations? let alone search them. the sticky sludge of communication in something as simple as chat has cost me hours since i was forced to use teams. outlook search is so superior to teams i'd easily prefer to have lync back. this one thing absolutely cripples communication. there are a list of other very basic issues that make…

Why don't the arrow keys work half the time in the chat input box?

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

#97

Not that it helps here, but Microsoft never considered the MSVCRT that ships with Windows to be public API. This is not the "Windows allocator", this is the (very) old MSVC runtime library's allocator. Of course that doesn't keep anyone from using this library because it's present on any Windows system, unlike the newer MSVC versions' runtime library. Using the allocator from a later MSVC's runtime library would prov…

>but Microsoft never considered the MSVCRT that ships with Windows to be public API It was in the past. At first msvcrt.dll was the runtime library used up to Visual C++ 6. Later, VC++ moved to their own separate dlls, but you could still link with system msvcrt.dll using corresponding DDK/WDK up to Windows 7. I'm also not sure that this is just ancient library left for compatibility, some system components still lin…

I don’t think msvcrt is exposed to link against in the DDK anymore. I maintain this, with the caveat that you really need to know what you’re doing: https://github.com/neosmart/msvcrt.lib

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

#98
post #20

Well... Who told you to link to MSVCRT (the one in System32)? Not Microsoft that's for sure. New software is supposed to link to the Visual Studio C runtime it was compiled with and then ship that library alongside the application itself. Even if you don't compile with VS you can distribute the runtime library (freely downloadable from some page on microsoft.com). Ostensibly, that library contains an efficient malloc…

there's a weird licensing thing for the VC runtime where you can't redistribute the dll alongside your code unless you have a special license. instead, you have to install it as an MSI. I have no idea why they created that restriction. I even work for MS and it baffles me.

probably so it gets a consistent installation location that is protected by the operating system. read the Raymond Chen blog post linked here a few times to see why not doing this has bitten Microsoft in the past.

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

#99

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…

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 work unless I can dismiss it early by versioning causing it to not link at all.

And given that glibc backward compatibility for all practical purposes is shorter than 10 years, having to support centos can get you a lot of those issues

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

#100

Earlier quoted context omitted.

It isn't mandatory. I have never actively linked against MSVCRT on Windows. From my experience it's mostly software that isn't built with Visual Studio that uses MSVCRT, or software that that takes extreme care of its binary size (e.g. 64k intros). MSVCRT is not even an up-to-date C runtime library. You wouldn't be able to use it for writing software requiring C11 library features without implementing them somewhere…

If you're writing in C++ on Windows, expose only COM (or at least COM-style) interface called through virtual functions on an object pointer. Then you can use whatever C++ run-time you want, internally. What you don't want is the other library calling C++ functions by name. Like you pass it some ostream object and it calls ostream::put or whatever, where that symbolically resolves to the wrong one.

It's also why all, or nearly all, new API on windows are done through COM.

It also means that C++ or other runtimes don't pollute your ABI and make it annoyingly hard to access features from any random code.

Post reply on HN