7 ms·
If I made my own criticism of these rules it would be very different from OP. It was difficult to take the article serious from the get-go when it defended setj
by AndyKelley 2y ago
If I made my own criticism of these rules it would be very different from OP. It was difficult to take the article serious from the get-go when it defended setjmp/longjump. That pattern is so obviously broken from anyone who has ever had to go near it. The article makes an argument like this:
1. setjmp/longjmp is exception handling
2. exception handling is good
and I take serious issue with that second premise.
Also the loop thing obviously means to put a max iteration count on every loop like this:
for (0..N) |_| {
}
where N is a statically determined max iteration count. The 10^90 thing is silly and irrelevant. I didn't read the article past this point.
If I were to criticize those rules, I'd focus on these points:
* function body length does not correlate to simplicity of understanding, or if anything it correlates in the opposite way the rules imply
* 2 assertions is completely arbitrary, it should assert everything assertable, and sometimes there won't be 2 assertable things
- bluGill 2y agoException handling in non trivial code is more performant than all the if else sequences to handle errors - if you even handle errors which odds are you won't. but it needs to be in the language so that the tricky code is write once.
- throw-qqqqq 2y agoThe part about “non trivial code” does a lot of lifting here. I would say your statement is untrue in general in at least a few languages. In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code. Other languages may have cheaper exceptions, but for many mainstream languages, you pay a big performance price for exceptions. That price is often offset by other positive things, so the tradeoff is made willingly and with eyes open.
- elygre 2y agoYou pay the cost only when the exception is raised. If that happens on more than 1% of your runtime checks, it probably is not (aka should not be) an exception.
- tempodox 2y agoYou wouldn't run .NET or Java on a spacecraft MCU and setjmp/longjmp in C are as cheap as it gets for exception handling.
- jayd16 2y ago> In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code. The conjecture is that if checks are always executed while exceptions are free when not thrown. That said, predicted branches are also fairly free so arguing about this in the abstract is pointless.
- rocqua 2y agoIn the margin, branches are more likely close to the hot path, so they are more likely to 'pollute' the instruction cache. Whilst exceptions have less of this. Though profile guided optimization will probably catch this. And it might be that even without, compilers still optimize around this.
- mkleczek 2y ago> In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code. Don't know about .NET but in Java it is not throwing exceptions that is heavy but filling in stack trace during construction of a Throwable. It can be made much more performant using constructor that disables stack trace: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Throwable.html#%3Cinit%3E(java.lang.String,java.lang.Throwable,boolean,boolean) https://docs.oracle.com/en/java/javase/21/docs/api/java.base...
- AlotOfReading 2y agoRealtime programming often compromises throughput ("performance") in order to make static deadline guarantees possible. Software exceptions, especially the tabled variety that are actually performant, are notoriously difficult to balance here and extremely uncommon even these days.
- eptcyka 2y agoHow will your code decide to throw? Continue down the happy path until the OS sends a signal? How does your business logic choose to throw if not by checking input and output values?
- kevin_thibedeau 2y agoHardcoded loop bounds are a requirement for running on hardware that will not be 100% reliable due to operating in the space radiation environment. Paranoid levels of defensive programming are a requirement for this regime. I would trust NASA's experience here rather than an armchair expert.
- cjbgkagh 2y agoDon’t they have voting CPUs? If one goes out of sync discard that result and restart it. And wouldn’t the value end up on the CPU the same if it was hardcoded or not? Perhaps there could be some verification done with hardcoded loop bounds for making sure things work in real time. I’ll read the article before commenting further. Edit: Yeah, the hardcoded bounds is to give some sort of guarantee as to how long a function will take.
- mr_toad 2y agoI’ve only heard of voting CPUs being used on launchers. I think the level of redundancy on other craft varies.
- fuzztester 2y agoiirc, I read about voting CPUs (like 4 of them) being used on space shuttles or earlier spacecraft. I could be wrong though.
- pauldino 2y agoThat's not the case for JPL missions (the paper originally is from JPL) which generally have 2 separate independent computers where 1 is active at a time. Since they're independent, the 2 computers don't actually have to run the same software, I believe during Mars entry descent and landing the standby compute element runs a different less sophisticated but easier to validate version of the EDL code to take over if any fault is detected while the primary software is running. (I was going to do a quick check on dataverse.jpl.nasa.gov to confirm that but it seems to be down) Also I think a few years ago on the Mars Curiosity rover (2012) there was some corruption in the flash storage on one of the computers that prevents the full flight software from being loaded on to it, so instead it runs a stripped-down version of the code with very limited functionality to function as a lifeboat in case the fully-working computer ever fails. https://ieeexplore.ieee.org/document/9843266 https://ieeexplore.ieee.org/document/9843266
- caspper69 2y agoHi Andy, it's been a long time since I pestered you. Glad to see Zig coming along so well. Congratulations on the progress! I'll apologize in advance for the long post. Wrt exceptions, you didn't elaborate. Exception handling can be a hot button issue with passionate opinions. My comments are general in nature; they are not specifically directed toward you or the Zig language. IMHO, exception handling is inherently neither good nor bad- it is merely a mechanism; it has upsides and downsides, and the context in which they are being discussed / analyzed / used should be the guiding factor. C provides no bounds or overflow checking. In the context of a system which must not fail, you are then forced to use some combination of rigorous assertions, overflow flag checking, and return value verification. It's cumbersome and ugly. Rust provides both bounds checking and overflow checks (in debug mode at least). Asserts are still available, but are not required in as many instances as in C. Neither of those languages provide what we would consider to be exceptions or exception handling. An argument could be made that if you squint the right way that Rust's resume after panic is a form of exception handling, but that's a semantic debate, and it would certainly be considered non-traditional if it were to be categorized as such. Wrt C, it had never occurred to me that setjmp()/longjmp() could be used as an exception handling mechanism. I have always seen them used as a context-switching mechanism for e.g. tasking (green-threads). In languages that provide exception handling, both runtime and user defined exception conditions are handled by the runtime itself (oftentimes behind the scenes). This mechanism allows one to provide a catch-all lexical scope for handling exceptions, which can be cleaner and more ergonomic from a programmer perspective and can be simpler to reason about (although this is certainly debatable). It also provides an opportunity to handle conditions that might be unknown or unforeseen at the time the code is being written. Defer semantics in a language without exceptions might be considered a mid-ground approach. The usual complaints with exceptions are: (1) that they essentially constitute hidden control flow and hidden code execution that happens outside of the plain reading of the source; (2) that you pay the performance penalty for checking / verifying the exception conditions at every line of code (also see #1); (3) that the conditions considered "exceptional" by most implementations are instead just run-of-the-mill error conditions that should be handled explicitly; and (4) that there is no well-defined structure or convention for where and when to handle exceptions and when to pass them up the stack (again, see #1) which results in a spaghettification of sorts. C++ (optional), Java, JS, Python and C# (among many others) all provide exception handling and are all mainstream. My general rule of thumb (which is always subject to situational variance) is that application code benefits from robust exception handling while systems level or performance critical code should not use exceptions, or at a minimum should be very judicious with usage. Exceptions can be abused and misused like any other feature, but the reduction in repetitive manual error checking (see Go) can be a win for many teams. YMMV of course- we have all been dragged into the 7th circle of hell at one time or another, and programming features are a lot like liquor; once you've gotten sick on one, it's near impossible to go back.
- AnimalMuppet 2y agoYeah, this read like he really wanted this to be a general set of guidelines instead of a C-specific set, and since they didn't explicitly say that they are C-specific, he's playing stupid "gotcha" games for whatever reason.
- lowbloodsugar 2y agoWhere did it say exception handling is good?
- cratermoon 2y ago> sometimes there won't be 2 assertable things It seems like if there's 1 assertable thing then it's trivial to also assert an inverse condition. Before arguing that it would be redundant, remember that in the presence of random bitflips and other anomalies caused by radiation exposure, logic may not operate as deterministically as expected.