grain-lang / grain

The Grain compiler toolchain and CLI. Home of the modern web staple. 🌾
https://grain-lang.org/
GNU Lesser General Public License v3.0
3.25k stars 114 forks source link

Rework: `toString` to use a buffer #2087

Open spotandjake opened 5 months ago

spotandjake commented 5 months ago

Currently toString in the runtime/string module rely's on concat for building the output string, this often incurs a performance penality from the many allocations done especially with more complex data structures like nested records. We implemented the bytes literal and a stdlib/buffer module into the language since toString was written. It would make sense to implement a basic buffer implementation in the runtime so we can make use of buffers throughout the stdlib and runtime. I think this would also help with maintainability of the toString function long term.

One note is the advantage to concat over toString, is currently our stdlib/buffer grows by powers of 2, in a memory confined environment this behaviour might not be ideal, we could add a new compiler flag though such as --low-memory which could configure the autogrow function to grow at a slower pace. This flag also might be useful in the future for other stdlib and runtime functions.

ospencer commented 5 months ago

To be clear, concat takes a list of strings and returns one large string—it's not concatenating two strings over and over. This would remove the allocations for the list cons cells which would be a large improvement, but not a dramatic one.

I do not think we should add a compiler flag to modify the growth behavior. It's complexity we don't need right now and would show little benefit. Switching to a buffer already improves memory consumption a lot.