3 ms·
Thanks for posting the link. The video is useless, it's just rage-baiting. Stepping back from the emotional overreaction in the OP, this seems to be the releva
by titzer 3y ago
Thanks for posting the link. The video is useless, it's just rage-baiting.
Stepping back from the emotional overreaction in the OP, this seems to be the relevant bit:
> Right off the bat, as a total Rust newbie, I'm hitting all kinds of rough edges in Rust. For example, I'm trying to use rusqlite. It would be natural to stash DB prepared statements in a thread local for reuse in my multi-threaded code. I can't pass the connections around, because I need them in a C call-back (too much detail here I know) so I have to be able to look them up. Alas, after banging my head against the wall for a full day, I'm just giving up on the thread-local approach, because I simply can't get it to work. Part of the problem is that I can't stash a prepared statement in the same (thread local) struct as the connection from which they are created, due to lifetime limitations. It also seems that you can't really use two thread locals (one for the connection and one for the prepared statements) either. If there's a way to do it, I can't figure it out.
What I take from this is that the library was designed to work with lifetimes a specific way, and the OP is trying to use them in a way not intended. Rust lifetimes being baked into the language means there is really no way around the design the library authors had in mind. If the library authors made bad choices, you are basically stuck.
This is the crux of the matter. A poorly designed library in Rust comes with a straightjacket that you must wear. I've had students hit this kind of things several times. This kind of experience absolutely kills the flow and sucks all the joy out of programming. Poorly-designed lifetimes are non-composable and lead programmers down completely unnecessary, totally unproductive rabbit holes.
Making memory management orthogonal APIs is the only way to make them composable.
- cmrdporcupine 3y agoI actually ran into these precise problems with rusqlite and found them equally frustrating, and ended up ripping that code out in the end. The lifetimes model in that library are, IMHO, "wrong".
- mike_hearn 3y agoIt seems almost worse - the author of rusqlite replies and says, essentially, that you just cannot do what he wants to do at all, and the "fix" is to either constantly re-prepare statements, or rely on some sort of library built-in cache! The first will lower performance perhaps by a lot, but performance is probably why you're writing Rust in the first place. The second is a nasty hack that will require you to remember this cache exists and keep its size carefully tuned. As all he wants to do is stash prepared statements in TLS, a pretty normal task, it seems like a valid complaint that this is so hard and rustql doesn't seem to allow it. One aspect of Rust I wonder about it is that when reading it I see way more cloning than you'd intuitively expect. Seems like people hit the borrow checker, can't see a way out and just copy the memory to escape. Presumably that will lead to diffuse performance losses all over the app of the sort that can't easily be spotted in a profiler, sort of like pointer chasing in languages without value types. I wonder if C++ will actually end up having an edge in performance due to this. I know there are very heavily tuned benchmarks that show Rust being the fastest but I mean for "real" code of the sort this person is needing to write (done under time pressure).
- titzer 3y agoYeah, it seems like suffering little tiny copies all over the place is regressing back to the thinly-spread performance sludge that Rust's ownership is designed to police and therefore eliminate. If it becomes too widespread a problem, then compilers will be tempted to start intrinsifying and then eliminating copies in order to make them fast and go away, which unfortunately will always come with cliffs where the compiler misses an opportunity. So the game theory of that in the end is that programmers do less and less and compilers do more and more. Maybe this is an inevitable dynamic between compilers, library writers, and application writers? Seems to have played out in many languages.