6 ms·
Partially true. In practice people implement multiplexed servers, for many reasons, including performance / throughput. A logic failure should nuke _the offendi
by fatherzine 4y ago
Partially true. In practice people implement multiplexed servers, for many reasons, including performance / throughput. A logic failure should nuke _the offending request_, not the entire server with all the unrelated concurrent requests.
- AshamedCaptain 4y agoThis is an attitude that I often see -- library authors who believe they own the process. Aborting may be the only sensible thing to do in runtimes where you can end up corrupting the entire process memory or the like, making recovery "dubiously possible", but absolutely not for anything higher level, where recovery may be safe and possible.
- burntsushi 4y agoI gave examples covering this area in the post. How would you rewrite the code in this section[1], for example, to conform to your views? (Assume this code is in a library.) [1]: https://blog.burntsushi.net/unwrap/#what-about-when-invariants-cant-be-moved-to-compile-time https://blog.burntsushi.net/unwrap/#what-about-when-invarian...
- fatherzine 4y ago* Short term: add explicit runtime checks for every step that may panic. With the way jump prediction works in modern processors, the runtime cost may be smaller than one may naively assume it is. Some of us would take, say, a 10% perf. degradation instead of chasing prod panics in the middle of the night. * Long term: plug-in a richer type (logic) system, so one can safely prove the most costly runtime invariants at compile time.
- burntsushi 4y ago> add explicit runtime checks for every step that may panic And do... what when the check fails? Can you please write the code for it? Because I don't understand what the heck you mean here. If you don't know Rust, pseudo code is fine. > Long term: plug-in a richer type (logic) system, so one can safely prove the most costly runtime invariants at compile time. This is just copying what I already said in the blog post. Until someone can show me how to prove the correctness of arbitrary DFA construction and search from a user provided regular expression pattern and demonstrate its use in a practical programming language like Rust, I consider this a total non-answer, not a "long term" answer. Basically, your answer here confirms for me that your views on how code should be structured are incoherent.
- fatherzine 4y agofn is_match(&self, haystack: &[u8]) -> Result<bool, Error> { ... }
- burntsushi 4y agoThat's exactly what the next section of my post explores and explains why it's complete bonkers: https://blog.burntsushi.net/unwrap/#why-not-return-an-error-instead-of-panicking https://blog.burntsushi.net/unwrap/#why-not-return-an-error-... So it looks like I already provided a rewrite of the code for you in your preferred style: // Returns true if the DFA matches the entire 'haystack'. // This routine always returns either Ok(true) or Ok(false) for all inputs. // It never returns an error unless there is a bug in its implementation. fn is_match(&self, haystack: &[u8]) -> Result<bool, &'static str> { let mut state_id = self.start_id; for &byte in haystack { let row = match state_id.checked_mul(256) { None => return Err("state id too big"), Some(row) => row, }; let row_offset = match row.checked_add(usize::from(byte)) { None => return Err("row index too big"), Some(row_offset) => row_offset, }; state_id = match self.transitions.get(row_offset) { None => return Err("invalid transition"), Some(&state_id) => state_id, }; match self.is_match_id.get(state_id) { None => return Err("invalid state id"), Some(&true) => return Ok(true), Some(&false) => {} } } Ok(false) } My favorite part is the docs that say "this never returns an error." Because if it did, the code would be buggy. And now all sorts of internal implementation details are leaked. You can't even document the error conditions in a way that is related to the input of the routine, because if you could, you would have discovered a bug! Another nail in the coffin of your preferred style is that this will absolutely trash the performance of a DFA search loop.
- fatherzine 4y agoMan, I only gave some friendly feedback ;) "this will absolutely trash the performance of a DFA search loop." Do you happen to have some hard data to quantify? I'm curious.
- winstonewert 4y agoYour short term suggestion appears confused. Panics are already the result of runtime checks. The issue isn't whether or not we have runtime checks, but what to do when those checks fail. But to your original point, its true that a multiplexing server should probably try to stay up even if there is a bug uncovered in handling a request. But that's precisely why rust allows you to catch panics.
- fatherzine 4y ago"It is not recommended to use this function for a general try/catch mechanism. The Result type is more appropriate to use for functions that can fail on a regular basis. Additionally, this function is not guaranteed to catch all panics, see the “Notes” section below." https://doc.rust-lang.org/std/panic/fn.catch_unwind.html https://doc.rust-lang.org/std/panic/fn.catch_unwind.html Edit. Re. already existing runtime checks, I'd expect a decent compiler to optimize away redundant checks, i.e. explicitly coded checks vs. checks injected automatically by the compiler, as long as their semantics is identical.
- burntsushi 4y agoCan you point to any compiler in the world that can see through the construction of a DFA from user input to the point that it can automatically optimize away the transition table lookup? > The Result type is more appropriate to use for *functions that can fail on a regular basis.* Emphasis mine. The DFA::is_match routine can never fail on any input. Yet, you want to use a 'Result' with it. Seriously. Please please pretty please read the blog post. You are literally caught in precisely the tangled mess that I tried to untangle in the post. If my post didn't do it for you, then please consider responding to specific points you disagree with in the post.
- fatherzine 4y agoSorry, I only meant to address with some nuance the statement "A failure with logic should nuke due to the app being in an inconsistent state". If you are confident that the specific DFA code in the blog post will not fail, more power to you! And to us, which transitively trust the code via your judgment ;) Edit. For technical geeking around: * The point is about redundant check elimination, not full check elimination. A decent compiler should be able to eliminate redundant checks, though perhaps the language could offer some intrinsics (was: pragmas) to make this 100% reliable. * For DFA proofs, perhaps something like https://courses.grainger.illinois.edu/cs373/fa2013/Lectures/lec03.pdf https://courses.grainger.illinois.edu/cs373/fa2013/Lectures/... could be a start. A great intern may tackle it over a summer ;)
- AshamedCaptain 4y agoExceptions.
- burntsushi 4y agoBzzt. Rust doesn't have exceptions. It has panics. And that's exactly how it's already implemented. If there's a bug, it panics. If you mean "return an error instead," then bzzt again. Read the next section down.
- AshamedCaptain 4y agoBzzt to the language, if anything. Panic practically everywhere is just not an admissible option, most definitely not for anything that tries to call itself a systems language. Proving that there is no reasonable alternative would be equivalent to claiming the language is unusable.
- burntsushi 4y agoThank you, Random Internet Stranger, for teaching me such a valuable lesson. I now know never to use any language that is Turing complete.
- lmm 4y agoTuring complete languages are legacy cruft. There are no compelling use cases where they're actually more expressive, and sheer code execution performance is never the bottleneck in a realistic-sized system.
- burntsushi 4y agoFeel free to back it up with real examples. Otherwise, previous conversations with you have just been frustrating exchanges about pie-in-the-sky stuff. Just seems like you want to be bombastic for the sake of being bombastic. > and sheer code execution performance is never the bottleneck in a realistic-sized system. TIL that code execution perf doesn't matter and I've wasted almost a decade of my life focusing on it. Wow I wish you told me sooner! What a ridiculous comment.