3 ms·
"Use subclasses over enums" must be some niche advice. I've never heard it. The youtuber seems to be referring to some specific example (he refers to specific a
by Arnavion 4y ago
"Use subclasses over enums" must be some niche advice. I've never heard it. The youtuber seems to be referring to some specific example (he refers to specific advice from "them") so I guess there's some context in the other videos of the series.
re: the speedup from moving from subclassing to enums - Compiler isn't pulling its weight if it can't devirtualize in such a simple program.
re: the speedup from replacing the enum switch with a lookup table and common subexpression - Compiler isn't pulling its weight if it can't notice common subexpressions.
So both the premise and the results seem unconvincing to me.
Of course, he is the one with numbers and I just have an untested hypothesis, so don't believe me.
- anonymoushn 4y agoI think "them" is someone named Robert Cecil Martin, but I'm not sure if this example from the video appears in his book. What compiler are you using that devirtualizes every class hierarchy? I suspect that Casey is using C++ so he may (unfortunately) have multiple translation units in his program.
- Arnavion 4y ago>I suspect that Casey is using C++ so he may (unfortunately) have multiple translation units in his program. Yes, the video uses C++. Obviously if one compiles a library then the compiler has no way of knowing that other subclasses of `shape_base` do not exist. My point is that when compiling a binary as they are doing for their video, the compiler knows that there are no other subclasses that it needs to cater to. It might require LTO explicitly, of course. At the very least godbolt doesn't devirtualize without LTO [1], but godbolt itself breaks if I enable LTO [2] and I CBA to test locally right now. [1]: https://gcc.godbolt.org/z/498nKEzhK https://gcc.godbolt.org/z/498nKEzhK [2]: https://gcc.godbolt.org/z/WqhP3fzxK https://gcc.godbolt.org/z/WqhP3fzxK
- Tomis02 4y agoCorrect me if I'm wrong. Even if the compiler devirtualizes the classes, you still have the memory cost of storing the vtable pointer in each of the object instances (8 bytes for each instance), which means you need to do more fetches from memory. Does CPU prefetching negate the cost of these additional memory lookups?
- muricula 4y agoThe enum to tell what shape an object is costs something, probably 4 bytes. Storing the 8 byte vtable constant isn't so bad considering.
- adamrezich 4y agolooking at a value is faster than dereferencing a pointer—why is this controversial?
- muricula 4y agoTo fix 2, add '-fno-rtti' to the args: https://gcc.godbolt.org/z/zMdfx71qE https://gcc.godbolt.org/z/zMdfx71qE Unfortunately, gcc does not seem to devirtualize in your example
- int_19h 4y agoEven when the target is an app, said app might be loading DLLs at runtime which may contain other subclasses. The fundamental problem here is that C++ doesn't have a good abstraction to represent visibility of public types, since any other translation unit - even across the DLL boundary! - can re-declare the type and then derive from it. The only way to constrain visibility is to use anonymous namespaces, and that only works if the type can be confined to a single unit (that C++ compilers seem to ignore the optimization opportunities here in practice perhaps indicates just how rare this actually is).
- signaru 4y agoMartin Fowler's "Refactoring" also has "Replace Conditional with Polymorphism". I like the intent of the book but I don't follow it 100%. Another part of that book that tripped me is where he calls the same function with the same argument multiple times instead of saving the result in a variable for reuse.
- jameshart 4y agoThe existence of a refactoring in the Fowler refactoring catalog is not normative advice that it should always be applied. Refactoring also has “Extract Function” and “Inline Function” as refactorings. They can’t both be right… Refactorings are moves you can make. Choosing when to make them is up to you. In fact, Fowler provides guidance along with each refactoring suggesting when it might be applicable (i.e., not always)
- 10000truths 4y agoA compiler can only devirtualize a virtual call if it knows the underlying object’s type at compile time, which it certainly won’t for a runtime populated array of base class pointers. CSE doesn’t work across function boundaries unless those functions are inlined, which won’t happen with virtual functions due to the above.
- Arnavion 4y agoSee my reply to anonymoushn's comment.
- pulp_user 4y agoSaying things akin to "your compiler is bad" because it doesn't optimize stuff like this is a cop out. For one: Most compilers for most languages are bad by that metric, and interpreters don't even get to play. So this is not helpful for the vast majority of people. Waiting around for them becoming good is not a viable option. Second, say the compiler would perform good in this scenario. Cool, lets go up a notch, or two, and it would start performing bad again, because there are limits to what it can do in a reasonable amount of time. And if that limit were big that maybe wouldn't matter, but the limit is low, and so it does. Real programs are so much more complex than this example, that even if the compiler got 10 times better, it would still fail to optimize large parts of your real program.
- cma 4y agoFor interactive applications debug builds also need to be fast.
- strager 4y agoUnfortunately, we live in the real world where compilers do not do the things that you suggest that they ought to.