> One major limitation of malloc (and even the best implementations like jemalloc and dlmalloc) is that they try to use a single allocator for each data structure.
I’m not sure what this is supposed to mean, but it’s good to note that malloc will switch between different paths based on the allocation size and what memory it has available to service the request.
malloc() has incomplete information. It doesn't know that this allocation of 0 bytes is soon going to balloon to a few GB in a future realloc(), so if it starts in brk, it'll mmap later and memcpy the data over. The good news is that the caller knows this.
By saying "I want a sizeof(Cons) object" versus "I want a buffer that's going to get big and used for a long time" versus "I want a buffer that'll get big but go away right after" means you get to avoid these unnecessary operations. That's important because they really add up when dealing with lots of data. That's how replacing a complicated and intelligent malloc() which has to rely on heuristics to decide which of the "different paths" to follow can lose big to a simpler strategy.
I’m not sure what this is supposed to mean, but it’s good to note that malloc will switch between different paths based on the allocation size and what memory it has available to service the request.