4 ms·
If freeing the data structure in question takes this long, how much time are you wasting duplicating the data structure?
by cperciva 6y ago
If freeing the data structure in question takes this long, how much time are you wasting duplicating the data structure?
- deleted 6y ago[deleted]
- saagarjha 6y agoI’m actually very curious why it takes this long; is Rust memseting the buffer when dropping it? Edit: it seems like turning on optimizations seems to improve the situation quite a bit. Not sure why they were profiling the debug build.
- deleted 6y ago[deleted]
- firethief 6y ago> Edit: it seems like turning on optimizations seems to improve the situation quite a bit. Not sure why they were profiling the debug build. This is the most important point in the thread, since it invalidates the results for most purposes.
- saagarjha 6y agoNot completely, it's still 2-3 orders of magnitude slower.
- firethief 6y agoYou're right, I expected it would make a bigger difference
- dathinab 6y agoThe thing is it's not slow because rust is doing anything wrong or unoptimized, is slow because cleaning up insane amounts of memory allocations is slow. Also if you run this: ``` fn main() { ::std::thread::spawn(move || { println!("end")}); println!("Hello, world!"); } ``` You might notice that "end" might not be printed because the main thread exists before it prints and terminates the process. This means that the dropping might actually not happen if it's at the end of the program and nothing is faster then not doing the work. Also it's a not uncommon pattern in small user facing CLI to leak (memory) resources, as they (should) be cleaned up with the process termination.
- Reelin 6y ago> I’m actually very curious why it takes this long; is Rust memseting the buffer when dropping it? Regardless of memset and optimizations, consider a particularly complicated object which lives on the heap and contains hundreds of other nested objects (which themselves contain nested objects, etc). Now imagine that a significant fraction of them make use of RAII. That cleanup code can't be elided. That being said, it's a pretty bad example if they were actually profiling the debug build ...
- fpgaminer 6y ago> it seems like turning on optimizations seems to improve the situation quite a bit. I'm not seeing that on my local machine? Were you comparing on the Playground which would be quite variable in its results? > cargo build Compiling foo v0.1.0 (/private/tmp/foo) Finished dev [unoptimized + debuginfo] target(s) in 0.42s > ./target/debug/foo drop in another thread 52.121µs drop in this thread 514.687233ms > > > cargo build --release Compiling foo v0.1.0 (/private/tmp/foo) Finished release [optimized] target(s) in 0.47s > ./target/release/foo drop in another thread 48.418µs drop in this thread 548.005373ms
- saagarjha 6y agoI saw an increase of about 2x on my computer, though I didn't take too much effort to control for noise.
- bszupnick 6y agoThis code doesn't duplicate it. In Rust when a variable is sent as an argument to a function it's "ownership" moves to be in the scope of that function. https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html https://doc.rust-lang.org/book/ch04-01-what-is-ownership.htm...
- cperciva 6y agoYou're missing my point. Unless the only thing you want to do with your giant data structure is measure its size, you're not going to be passing ownership of your only copy of it into the get_size function. You're going to be passing in a copy -- hence the cost of duplicating everything.
- phyzome 6y agoIn the different contrived case where it gets copied, you'd instead change this code to take an immutable reference to it, and compute the size of that. Or you'd call .size() instead of calling this function!
- eMSF 6y agoIt is just an example. You can think of "measuring size" here as getting the result of a long computation that involves a lot of allocations. After you get the result, you no longer care about the intermediate stuff – i.e. all the allocations. You certainly don't want to duplicate them, you just want to get rid of them, and the author tells that you might not want to deallocate (drop) them in the UI thread. If it helps you, you might want to imagine the contents of the get_size function as being the end part of a longer calc_foo function. What's really missing the point is focusing so hard on the part that the example even contains a call to size() of a collection.
- ReactiveJelly 6y agoRust is stricter about aliasing than C++ is. Vectors are the size of 3 pointers (data, size, capacity), so I guess 24 bytes on x64. Even if the move requires a memcpy, it's only copying that 24 bytes - The heap allocation is not copied, because there are never two owners of the vector at once.