Live data from Hacker News

Box to save memory in Rust

dystroy.org

31–40 of 59 posts

Re: Box to save memory in Rust

#31

Very often if you have text, which this does, you can make huge savings by being intelligent with the text. Rust intentionally provides the simplest possible growable string buffer String, which is literally (under the hood, you can't poke this legitimately) Vec plus the promise that this is UTF-8 text. But you might find your needs better served by one (or several) of: Box -- you don't need capacity, so, don't store…

There's really an endless list of these optimizations. A few I've used (though not necessarily in rust): Atoms: Each string can be referenced with a single u32 or even u16, and they're inherently deduplicated. Bump allocator: your strings are &str, allocation is super fast with limited fragmentation. Single pointer strings (this has a name, I can't think of it right now): you store the length inside the allocation in…

> There's really an endless list of these optimizations.

These aren't really optimizations. They are specialized implementations that introduce design and architectural tradeoffs.

For example, Rust's Atom represents a string that has been interned, and it's actually an implementation of a design pattern popular in the likes of Erlang/Elixir. This is essentially a specialized implementations of the old Flyweight design pattern, where managing N independent instances of an expensive read-only object is replaced with a singleton instance that's referenced through a key handle.

I would hardly call this an optimization. It actually represents a significant change to a system's architecture. You have to introduce a set of significant architectural constraints into your system to leverage a specific tradeoff. This isn't just a tweak that makes everything run magically leaner and faster.

Re: Box to save memory in Rust

#32

Earlier quoted context omitted.

There's really an endless list of these optimizations. A few I've used (though not necessarily in rust): Atoms: Each string can be referenced with a single u32 or even u16, and they're inherently deduplicated. Bump allocator: your strings are &str, allocation is super fast with limited fragmentation. Single pointer strings (this has a name, I can't think of it right now): you store the length inside the allocation in…

Atoms: is this similar to interned strings?

> Atoms: is this similar to interned strings?

Yes. It is exactly how they are described.

https://docs.rs/string_cache/latest/string_cache/struct.Atom...

> Represents a string that has been interned.

Re: Box to save memory in Rust

#33
The jemalloc feature flag setup is the part I will steal from this. Not the boxing. In previous platform work we had the same problem: measure in dev with the wrong workload, or add permanent allocator overhead to prod. Feature-gating the instrumented allocator means the binary you measure is the binary you ship. Harder to arrange than it sounds once you've got environment-specific build configs in the way.

Re: Box to save memory in Rust

#34
post #27

Earlier quoted context omitted.

> String, which is literally (under the hood, you can't poke this legitimately) Vec `String::as_vec_mut` kinda implies that, since it gives you access to that underlying `Vec` which must then exist somewhere.

I looked it up: https://doc.rust-lang.org/std/string/struct.String.html#meth... In case anyone else was wondering it, yes, it's "unsafe".

The thing they were gesturing at, correctly, is the naming. This is of course a convention and not a promise, but by convention Goose::as_crow would be a function that is cheap and gets you say &Crow instead of the &Goose you might have now, whereas Goose::to_donkey suggests that although we can have a Donkey instead of this Goose it's expensive to do that.

Commonly as... conversions are actually no-ops at runtime (the type changes but the data does not, no CPU instructions are emitted) whereas to... conversions might do quite a lot, especially if they bring into existence an actual thing at runtime -- maybe Goose::to_donkey actually needs to go allocate memory for a Donkey and destroy the Goose.

Yes it's unsafe because the Vec doesn't enforce the promise we made about this being UTF-8 text whereas String did, so now that promise is ours to keep and `unsafe` is how we signify that you the programmer took on the responsibility for safety here.

Re: Box to save memory in Rust

#35

Very often if you have text, which this does, you can make huge savings by being intelligent with the text. Rust intentionally provides the simplest possible growable string buffer String, which is literally (under the hood, you can't poke this legitimately) Vec plus the promise that this is UTF-8 text. But you might find your needs better served by one (or several) of: Box -- you don't need capacity, so, don't store…

I wish Box and Option got specialized specialized shorthand syntax in Rust say `^`/ `? or something like that.

   Option -> SmithyTrait^?

Re: Box to save memory in Rust

#37
post #27

Earlier quoted context omitted.

I looked it up: https://doc.rust-lang.org/std/string/struct.String.html#meth... In case anyone else was wondering it, yes, it's "unsafe".

The thing they were gesturing at, correctly, is the naming. This is of course a convention and not a promise, but by convention Goose::as_crow would be a function that is cheap and gets you say &Crow instead of the &Goose you might have now, whereas Goose::to_donkey suggests that although we can have a Donkey instead of this Goose it's expensive to do that. Commonly as... conversions are actually no-ops at runtime (t…

Yes, naming does play a role here, but the biggest hint is `as_vec_mut` returning a reference. For that to work a `Vec` needs to exist somewhere, and continue to exist after this function returns. For comparison, `to_` conversions generally just return the new data, so this reasoning doesn't apply to them.

Re: Box to save memory in Rust

#38

Earlier quoted context omitted.

There's really an endless list of these optimizations. A few I've used (though not necessarily in rust): Atoms: Each string can be referenced with a single u32 or even u16, and they're inherently deduplicated. Bump allocator: your strings are &str, allocation is super fast with limited fragmentation. Single pointer strings (this has a name, I can't think of it right now): you store the length inside the allocation in…

> There's really an endless list of these optimizations. These aren't really optimizations. They are specialized implementations that introduce design and architectural tradeoffs. For example, Rust's Atom represents a string that has been interned, and it's actually an implementation of a design pattern popular in the likes of Erlang/Elixir. This is essentially a specialized implementations of the old Flyweight desig…

You might want to refresh your understanding of the word optimisation. Changing a system to be more effective/efficient is optimisation, how big that change is makes no difference.

Re: Box to save memory in Rust

#40
So there are now two ways to represent the same state: None or Some(struct whose fields are all None). Even though one of these representations is never produced by the deserialization routine, anyone could construct it if the constructor is public. And even if they don't, the different representations will show up in pattern matching as separate paths for every access to the field. This looks like a good opportunity to make these types (optimized for storage) private, and to define public view objects/accessors (optimized for usage) on top of them that merge equivalent representations.
Post reply on HN