4 ms·
> Is this actually a real optimization? No... And yes. No: Because throwing and catching the null pointer exception is hideously slow compared to doing a null
by gwbas1c 2y ago
> Is this actually a real optimization?
No... And yes.
No: Because throwing and catching the null pointer exception is hideously slow compared to doing a null check. In Java / C#, the exception is an allocated object, and the stack is walked to generate a stack trace. This is in addition to any additional lower-level overhead (panic) that I don't understand the details well enough to explain.
Yes: If, in practice, the pointer is never null, (and thus a null pointer is truly an exceptional situation,) carefully-placed exception handlers are an optimization. Although, yes, the code will technically be faster because it's not doing null checks, the most important optimization is developer time and code cleanliness. The developer doesn't waste time adding redundant null checks, and the next developer finds code that is easier to read because it isn't littered with redundant null checks.
- mr_00ff00 2y ago“Most important optimization is developer time and code cleaniness” True for 99% of programming jobs, but if you are worried about the speed of null checks, you are in that 1%. In high frequency trading, if you aren’t first your last and this is the exact type of code optimizations you need for the “happy path”
- wging 2y agoIf you're actually paying a significant cost generating stack traces for NPEs, there's a JVM option to deal with that (-XX:-OmitStackTraceInFastThrow). It still generates a stack trace the first time; if you're able to go search for that first one it shouldn't be a problem for debugging.
- LorenPechtel 2y agoYup, three is definitely value to the code not doing things it doesn't need to. I also find it clearer if the should-never-happen null check is in the form of an assertion. You know anything being tested in an Assert is a should never happen path, you don't need to consider why it's being done.
- gwbas1c 2y ago> You know anything being tested in an Assert is a should never happen path, you don't need to consider why it's being done That's also rather... Redundant in modern null-safe (or similar) languages. IE, Swift and C# have compiler null checking where the method can indicate if an argument accepts null. There's no point in assertions; thus the null reference exceptions do their job well here. Rust's option type (which does almost the same thing but trolls love to argue semantics) also is a situation where the compiler makes it hard to pass the "null equivalent." (I'm not sure if a creative programmer can trick the runtime into passing a null pointer where it's unexpected, but I don't understand unsafe Rust well enough to judge that.) But if you need to defend against that, I think Panics can do it.
- LorenPechtel 2y agoYou're assuming that you can always make your declarations correctly express whether something can be null. Let's consider a real world example I hit: Every cell has a concept of it's neighbors. Now, the world isn't infinite, some of those pointers are null. But there's a boundary layer of edge-of-the-world cells to keep you from going too far. Thus, in the real world null can never occur--but there are a gazillion places where it would have to test for a null that should never happen. Or simply Assert in the routine itself.
- gwbas1c 2y ago> You're assuming I'm not. It's pretty clear that you don't know how null safe Swift, C#, and Rust work. IE: Rust has the option type for when a value can be null, and the compiler forces you to do an "empty" check. Otherwise, null, does not exist in the language. Swift and C# are more metadata based. You indicate if a value supports null or not. The compiler will give you a warning, or error depending on configuration, if you try to assign null to a value that does not expect it. All three languages have a concept of values that can be null, (or empty in Rust if you want to argue semantics,) so your type system tells you when a value can be null, or when it is expected to not be null. In all three languages, the compiler can force you to make assignments before you use an object.