this conclusion might be wrong. the code in question while it might not be allocating/freeing memory it might be stumbling on memory blocks and corrupting mem management structures. Turning the flag on might be fixing the issue by mere luck because memory allocations, locations and structures would be different
The Horror in the Standard Library
31–40 of 222 posts
Re: The Horror in the Standard Library
#32Yeah malloc() is pretty terrible in glibc by modern standards. For some workloads it just can't keep up and ends up fragmenting space in such a way that memory can't be returned to the OS (and thus be used for the page cache) and you end up in this performance spiral. I always deploy C++ server on jemalloc. Been doing it for years and while there's been occasional hicks up when updating it has provided much more pred…
Actually from my understanding, it's libstdc++'s allocator that is causing the issue, not malloc.
We're not talking about another optimization (small object / locality) as his issue was caused by libstdc++ alloc pools which would not need to exist in the first place if system malloc was better. So libstdc++ reinvents end up reinventing the wheel poorly.
As the author mentioned, when he disabled the optimization behavior GLIBCPP_FORCE_NEW he ended up burning more CPU via system (glibc) malloc(). Once he added jemalloc on top of GLIBCPP_FORCE_NEW, this pretty much evened out with previous behavior runtime performance.
The conclusion towards the end of article: > The right answer to "malloc is slow" is to make it faster.
Re: The Horror in the Standard Library
#33Actually it is C's malloc and free that is "broken". malloc() takes a size parameter, but free() doesn't. This imbalance means it can never be maximally efficient. Whatever GNU stdlibc++ is doing is probably, on balance, a net win for most programs. It's not exactly roses in C++ either of course. You can do better than the standard library facilities. Andrei Alexandrescu gave a great, entertaining, and technically el…
The C++ delete[] operator doesn't take a size parameter either. This is neither here nor there, and unrelated to the problem the blog post is talking about.
Re: The Horror in the Standard Library
#34Re: The Horror in the Standard Library
#35Have you tested to see if this works better with LLVM libc++?
Re: The Horror in the Standard Library
#36I myself ran across this same scenario many years ago with a similar amount of hair pulling and eventually concluding that the GNU libstdc++ allocator wasn't reusing memory properly. Unfortunately, I was never able to pare down the application to the point that I had a reproducible test case to report upstream. GLIBCPP_FORCE_NEW was the solution for the near term and since I was deploying on Solaris boxes I eventuall…
It really bugs me that nobody links bug on bugtracker or filed it. I know I'm asking a lot and being an ass.
[0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=13823
Edited to add the following text.
There is one result[1] for GLIBCXX_FORCE_NEW.
Re: The Horror in the Standard Library
#37Actually it is C's malloc and free that is "broken". malloc() takes a size parameter, but free() doesn't. This imbalance means it can never be maximally efficient. Whatever GNU stdlibc++ is doing is probably, on balance, a net win for most programs. It's not exactly roses in C++ either of course. You can do better than the standard library facilities. Andrei Alexandrescu gave a great, entertaining, and technically el…
If free() took a size, what would that buy you? You are aware that malloc implementations tend to stick the size just before the part returned to the caller, right? eg. let's say you store size at p, return p+4 to caller, then have free() subtract 4 again to get at this "header"... So I'm guessing that's not your suggestion because free() wouldn't work at all without that kind of hack. Or more broadly, free() or real…
Re: The Horror in the Standard Library
#38Earlier quoted context omitted.
If free() took a size, what would that buy you? You are aware that malloc implementations tend to stick the size just before the part returned to the caller, right? eg. let's say you store size at p, return p+4 to caller, then have free() subtract 4 again to get at this "header"... So I'm guessing that's not your suggestion because free() wouldn't work at all without that kind of hack. Or more broadly, free() or real…
With the status quo, say you call malloc() once. After a long while you call free(). Now the first thing free() needs to do is figure out the size, which is stored "before" the pointer. Until that load is complete, it can't know how large the allocation was, so it can't prefetch other necessary data, e.g. the free list for a given chunk size. This could add 120 cycles of latency to get a value that the caller probabl…
Edit to add: I've used both malloc()/free() and a custom memory allocation API that required the size to be passed in. I found the second API to be much more of a pain to use over the long term. Besides, it wastes memory because the memory API will have to track the size anyway to detect misuse of the API (or else blindly trust that the right size is passed in and hilarity ensues when it's not ...).
Re: The Horror in the Standard Library
#39Earlier quoted context omitted.
It really bugs me that nobody links bug on bugtracker or filed it. I know I'm asking a lot and being an ass.
I searched GCC Bugzilla and found one result[0] for GLIBCPP_FORCE_NEW. [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=13823 Edited to add the following text. There is one result[1] for GLIBCXX_FORCE_NEW. [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65018
Re: The Horror in the Standard Library
#40Did you report the issue upstream with a patch? The solution to "the standard library is broken" is to fix the standard library, no? It's all free software after all.
Doesn't the author make that case at the end?