4 ms·
I have the same experience in C applications, but not in Rust. Rust's problems are IMHO purely self-imposed from unnecessarily nihilistic assumptions. • There'
by pornel 5y ago
I have the same experience in C applications, but not in Rust. Rust's problems are IMHO purely self-imposed from unnecessarily nihilistic assumptions.
• There's no problem of "untested error paths". Rust has automatic Drop. Cleanup on function exit is written by the compiler, and thus quite dependable. Drop is regularly exercised on normal function exits too.
• Overwhelming majority of Drop implementations only free data, and don't need to allocate anything. Rust is explicit about allocations, so it's quite feasible to avoid them where necessary (e.g. if you use a fat error type that collects backtraces, that can bite on OOM. But you can use enums for errors, and they are plain integers).
• Probability of hitting OOM is linearly proportional to allocation size, so your program is most likely to hit OOM when allocating its largest buffers. This leaves a lot of RAM left to recover from that. It's basically impossible to exhaust memory up to the last byte.
Crashing may be fine for tiny embedded software or small single-threaded utilities. However, crashing of servers is expensive, and may not even work. When you crash, you kill all the requests that were in progress. This wastes work already done by other threads, and you're not making progress. When clients retry, you're likely to get the same set of requests that lead to OOM in the first place, so you may end up crashing and restarting in a loop forever. OTOH if you detect OOM and reject one offending request, you can keep making progress with other smaller requests.
- lmilcin 5y agoCompiler can only do limited number of things and I am not talking about it. Think in terms of trying to save the file you are working on before the application exits. Or notify cluster map that the node is not going to be available to process requests. How does compiler factor in it?
- pornel 5y agoYou don't exit. You work with fallible functions, and keep trying to handle errors for as long as possible. Each function can fail, and when it fails, you propagate the error up to a point where the whole failing task can be gracefully cancelled. e.g. if user invokes a "Print" command, and it runs out of memory, then instead of immediately crashing and burning, you can try to report "Sorry, print failed". That too will be handled fallibly, so if `message("Sorry…")?` fails, then you proceed to plan B, which may be log, then save and quit. If these fail, then finally crash and burn. But chances are that maybe print preview needed to allocate lots of memory, and other functions don't need as much, so your program will survive just by aborting that one operation.