Live data from Hacker News

All About Libpas, Phil's Super Fast Malloc

github.com

31–40 of 87 posts

Re: All About Libpas, Phil's Super Fast Malloc

#32

General purpose memory-allocation is a lie. Everything has use cases where they're faster than other libraries. I think that's why we keep seeing newer malloc schemes pop up, because the performance of the heap 100% depends on the use-case, and different people have different use cases. Still, studying everyone else's heaps (and garbage collectors, a closely related discussion) is probably good for high-performance p…

I've seen a few opensource projects archive their custom allocators because they were not beating the system's one or jemalloc. So if you have the skill and time then yeah go for it, else stick with general purpose ones.

Re: All About Libpas, Phil's Super Fast Malloc

#33

General purpose memory-allocation is a lie. Everything has use cases where they're faster than other libraries. I think that's why we keep seeing newer malloc schemes pop up, because the performance of the heap 100% depends on the use-case, and different people have different use cases. Still, studying everyone else's heaps (and garbage collectors, a closely related discussion) is probably good for high-performance p…

100%, and also I think there's a tendency among people who compare 'higher up the stack' in GC'd languages to manual heap allocation in C/C++ etc. in a way that implies the the latter is almost "free" from a performance POV when in fact underneath the covers in these allocators there's still a lot of the same kind of walking of datastructures that also happens inside a tracing GC.

You can get unpredictable pauses from malloc/free, too.

Re: All About Libpas, Phil's Super Fast Malloc

#34

Hey Phil, thanks for the write up! Curious why this is only used for JSC's JIT, and not to back its heap? Did the design of the JSC GC influence libpas at all?

It's used for JSC's JIT and for all heap allocations in JavaScriptCore and WebKit that aren't GC allocations.

Riptide (the JSC GC) has a similar design and some of the key ideas were first pioneered there:

- The use of fast bitvector searches to find an eligible page (Riptide calls it first eligible block, I think).

- The use of bitvector simd to change object states in bulk.

- Riptide uses a mark bitvector that is indexed by minalign atom (16 bytes) and a block size of 16KB. Libpas's default "small segregated" configuration is 16 byte minalign, 16KB block, and an alloc bitvector indexed by minalign.

I have since thought about how Riptide could be wired up to use libpas. It's possible to do it. Already today you could create a libpas page_config that leaves room for mark bits in the page header, and makes them use the same indexing as the alloc bits. Riptide has a "newly allocated" bitvector that serves almost the same purpose as the alloc bits (kinda, if you squint really hard) - so you'd go from Riptides newly_allocated and mark bitvectors, to libpas's alloc bitvector and a custom mark bitvector stuffed into page headers using an exotic page_config. If JSC did this, it would buy:

- Better decommit policies than Riptide. I did a lot of tuning in libpas to make decommit Just Right (TM).

- Faster allocation of medium-sized objects.

- Possibly better memory efficiency.

But, Riptide is already very nicely tuned, and it gets some benefit from libpas's decommit rules because Riptide calls fastMalloc to get memory and sometimes uses fastFree to return it. fastFree calls bmalloc::api::free, which calls libpas's bmalloc_deallocate, which then goes to pas_deallocate with the BMALLOC_HEAP_CONFIG. So, Riptide already gets some of the goodness of libpas by sitting on top of it.

Re: All About Libpas, Phil's Super Fast Malloc

#35

Earlier quoted context omitted.

> There's no easy way to tell the C++ compiler, "please make only one version of foo and use callbacks to figure out what it means to += on T". Partial counterpoint: you could use class polymorphism, if T is always a type you control. But you're right in general; C++ doesn't have typeclasses or some other way to create an ad-hoc vtable for, say, int. > Now, if you want monomorphization like C++, call foo() and pass a…

Yes, it works with structs of function pointers. And it works recursively. This works (this is slightly shorthand C, fill in the blanks yourself): struct config { void (*foo)(things bar); stuff (*bar)(int baz); }; always_inline stuff doit(config c) { c.foo(whatever); return c.bar(42); } always_inline void my_foo(...) { ... } always_inline stuff my_bar(...) { ... } stuff dostuff(void) { config c; c.foo = my_foo; c.bar…

Got it. That is definitely a cool insight. Thanks for sharing!

Re: All About Libpas, Phil's Super Fast Malloc

#36

General purpose memory-allocation is a lie. Everything has use cases where they're faster than other libraries. I think that's why we keep seeing newer malloc schemes pop up, because the performance of the heap 100% depends on the use-case, and different people have different use cases. Still, studying everyone else's heaps (and garbage collectors, a closely related discussion) is probably good for high-performance p…

100%, and also I think there's a tendency among people who compare 'higher up the stack' in GC'd languages to manual heap allocation in C/C++ etc. in a way that implies the the latter is almost "free" from a performance POV when in fact underneath the covers in these allocators there's still a lot of the same kind of walking of datastructures that also happens inside a tracing GC. You can get unpredictable pauses fro…

I think in either case, GC or not, you write something intuitively and then when it becomes an actual problem, you study the patterns and improve them, but most of the time you can leave it alone and the general purpose thing is good enough.

Or if you are in a niche like audio/video or something, you avoid allocations all together during the bulk of the code.

Re: All About Libpas, Phil's Super Fast Malloc

#37

Earlier quoted context omitted.

100%, and also I think there's a tendency among people who compare 'higher up the stack' in GC'd languages to manual heap allocation in C/C++ etc. in a way that implies the the latter is almost "free" from a performance POV when in fact underneath the covers in these allocators there's still a lot of the same kind of walking of datastructures that also happens inside a tracing GC. You can get unpredictable pauses fro…

I think in either case, GC or not, you write something intuitively and then when it becomes an actual problem, you study the patterns and improve them, but most of the time you can leave it alone and the general purpose thing is good enough. Or if you are in a niche like audio/video or something, you avoid allocations all together during the bulk of the code.

Oh for sure. Premature optimizing is usually bad form.

What is tricky about performance issues in allocation is that they can be hard to profile. There are tools for analyzing GC performance in GC'd languages, but sometimes malloc/free can just be a big black box.

Re: All About Libpas, Phil's Super Fast Malloc

#39

Earlier quoted context omitted.

I never got a chance to compare it to those, since I was most interested in beating bmalloc. And I mainly wanted to beat it on Safari workloads. I believe bmalloc was previously compared against jemalloc and tcmalloc, also using Safari workloads, and bmalloc was significantly faster at the time.

For other people who have never heard of bmalloc - it's a custom allocator used only by WebKit. I guess it's not surprising they added one since the Mac system allocator is extremely slow. A custom allocator is pretty much a free 20% speed up on Mac (depending on your workload) but I found they made no difference on Linux. Haven't tried on Windows.

Just some credit where credit is due.

I measured the system malloc crushing all other mallocs on some workloads and they were the kind of workloads that some folks run every day.

I measured the system malloc crushing most other mallocs on memory efficiency on most workloads. System malloc is really good at reusing memory and has very mature decommit policies that easily rival what I came up with.

So there’s that.

Post reply on HN