Sharing memory allocation across multiple calls while taking an immutable reference to self

TL;DR: How can I avoid allocating the same amount of memory in a method which is ran multiple times while taking a immutable reference to self at the same time?
I have a struct with a constructor and a eval method. The algorithm of the eval method needs a region of memory in the heap to work (not to transfer data). It can't be the stack because the amount of memory it needs is different depending on the inputs of the struct at construction, but this also means the capacity of the said region of memory doesn't need to change as long as the contents of the struct stays the same (since the fields of the struct aren't public then the said change is impossible). Since the eval method is ran in a hot loop in some use cases it's performance is important, so I moved the allocation of the required memory to the construction of the struct and only clear the Vector at the first line of eval. This posed the limitation of taking a mutable reference in the eval function only to make use of a region of memory, to the outside eye the mutable reference doesn't make sense. Eventually I ran into an issue myself and decided to allocate memory instead of clearing any Vector and taking a mutable reference and as the result all of my benchmarks turned red. How can I keep this region of memory across multiple calls while also not taking a mutable reference? I though of taking an optional Vector as an argument but it doesn't make sense when it's a method of a struct. I'm sure my issue is not even remotely unique so I would be very thankful for even the smallest lead or idea
I don't encourage anyone to read my code but here it is if you're really curious: https://github.com/Jroid8/math-eval/blob/main/src/asm.rs#L238

Sounds like you want interior mutability to me. I.e. maybe you can store the data in a Cell<[T]> instead of a vector. You could then use Cell::as_slice_of_cells in your eval method to update individual elements.

1 Like

Interior mutability is the most obvious option where you have a method that needs to update a cache, record usage metrics or do other things inside a method which involve mutating data but don't logically change the state of the object.

Some other ways you could solve this:

  • Take the storage buffer as an argument (or an allocator or pool which provides the storage), as you mentioned
  • Use a thread-local storage buffer inside the function. This will be created once per thread.
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.