I'm attempting to write my first real Rust app, based on one I wrote in C. I'm looking for recommendations on the questions/ideas below. Any help is greatly appreciated!
The app has 2 phases. The first phase is single threaded, and builds a large cyclic graph data structure. No parts of the graph are deleted during the process. Nodes contain both individual links and dynamically sized collections of links to other nodes, along with strings and POD fields.
The second phase is multi-threaded, and traverses through various parts of the graph many times, but never does any modifications of the graph. A lot of the performance of the second phase depends on the speed of those traversals. Once in the second phase, the process will remain there (it's a long-lived server).
If I use interior mutability (using Cell
throughout), that makes the first phase pretty easy. But, that seems like it would remove the possibility of compiler optimizations during the second phase that take advantage of the total lack of modifications. Also, Cell
is !Sync
- so how would the graph become sharable by all threads in the second phase?
A wild idea is to have a pair of memory-identical representations for all node types in the graph - one that wraps Cell
on all fields and the other that doesn't. Then, do one unsafe cast of the entire graph (by casting its root) after the first phase from the Cell
version to the non-Cell
version. The second phase threads would share the non-Cell
version, which would be Sync
and get all the nice optimization benefits from the lack of further modifications. Does that sound crazy? I suspect that this paired-type setup could be keyed by a boolean generic parameter.
Or, is there a better way?
Also, what should I use to own the graph nodes (all of which are 'static
)? Some kind of arena?