We currently use dlmalloc for malloc/free, which is an excellent implementation. However, the code size of malloc/free don't matter in a native environment, but on the Web this can be an issue - in a small program using malloc/free, they can be a huge part of the total code size, so small libraries are paying a lot for malloc/free right now.
It might be worth investigating writing our own malloc/free, which might make a different set of tradeoffs, like being more compact in code size while having fewer optimizations for runtime speed.
I generalized the title here from malloc/free to custom compact libc methods in general, after some thinking about a comment by @joshtriplett.
The issue brought up there is that puts() could almost be optimized into just a tiny function that does some logging (which would avoid all the streams code overhead). That's what we should be able to do in a perfect world, but we can't because of buffering: musl streams perform buffering at the C level. That means that we can't just optimize puts the way we'd like, due to things like
printf("no newline");
puts("more");
The puts at the end must flush the buffered "no newline" text; it can't just directly log out what it receives ("more").
Really the issue is similar to malloc/free: we could write a more compact version tailored for the web use case. Specifically here, we don't need buffering in C at all, as buffering is a workaround for syscall slowness, but our "syscalls" are just calls out into JS. And more generally, we can do better than the linux syscall interface in other cases too, which was not designed for the web use case.
In other words, we could write a custom libc-for-the-web which is much smaller than even musl or newlib. This was almost what emscripten started out with, but that was 7 years ago and we made 2 mistakes: it was all in JS, and it rewrote difficult things like printf formatting. Instead, we should write what we can in C, and reuse what we can from existing libcs. We could get large improvements in code size for small programs that way, but it does mean doing more work.
This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.
Most helpful comment
I generalized the title here from malloc/free to custom compact libc methods in general, after some thinking about a comment by @joshtriplett.
The issue brought up there is that
puts()could almost be optimized into just a tiny function that does some logging (which would avoid all the streams code overhead). That's what we should be able to do in a perfect world, but we can't because of buffering: musl streams perform buffering at the C level. That means that we can't just optimizeputsthe way we'd like, due to things likeThe
putsat the end must flush the buffered "no newline" text; it can't just directly log out what it receives ("more").Really the issue is similar to malloc/free: we could write a more compact version tailored for the web use case. Specifically here, we don't need buffering in C at all, as buffering is a workaround for syscall slowness, but our "syscalls" are just calls out into JS. And more generally, we can do better than the linux syscall interface in other cases too, which was not designed for the web use case.
In other words, we could write a custom libc-for-the-web which is much smaller than even musl or newlib. This was almost what emscripten started out with, but that was 7 years ago and we made 2 mistakes: it was all in JS, and it rewrote difficult things like printf formatting. Instead, we should write what we can in C, and reuse what we can from existing libcs. We could get large improvements in code size for small programs that way, but it does mean doing more work.