<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">I was reading <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1240r1.pdf" class="">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1240r1.pdf</a>, which describes proposed reflection features currently under advanced consideration.  </div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">On page 5, the authors give their rationale for defining `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">reflexpr(x)</span>` to return an object of an opaque builtin type called `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">meta::info</span>`, which is useful only when passed to other builtin functions able to access its various properties for different reflected entities.  This design is favored over the alternative of defining it to return an AST-class-like object specific to each reflected entity (ReflectedDeclaration, ReflectedStatement etc.).  </div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">In other words given this design the user must write e.g. `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">meta::parameters_of(reflexpr(somefunc))</span>` instead of e.g. `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">reflexpr(somefunc)->parameters()</span>`.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">One rationale the authors give for this choice is that they found that accessing subobjects of a constexpr class object is significantly slower than accessing values which are not subobjects, all else being equal.  The authors present an example on pp 5-6.  </div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">I tried to reproduce this example and their results in CompilerExplorer, and was mostly just shocked at the apparent orders-of-magnitude-differences between GCC (by far the fastest), Clang, and MSVC (by far the slowest) at both constant-evaluation tasks.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Example A (NB `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">f()</span>` deals only with complete objects):</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><a href="https://godbolt.org/z/TM5Wb6" class="">https://godbolt.org/z/TM5Wb6</a></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Example B (same as A, except `<span style="font-stretch: normal; line-height: normal; font-family: Menlo;" class="">f()</span>` now defined to dig through subobjects to get the data it needs):</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><a href="https://godbolt.org/z/5dPq3W" class="">https://godbolt.org/z/5dPq3W</a></div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Results of 5 trials:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">                    __Compilation_times__</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">A</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">GCC  (1793B):   337,   408,   325,   435,   242 ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">Clang (218B):  9361,  5173,  4066,  5698,  4263 ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">MSVC  (306B): 21850, 24616, 24957, 24925, 32323 ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">B</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">GCC  (2295B):   471,   319,   403,   309,   323 ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">Clang (218B): 17073, 15540, 17281, 13385, 18540 ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo;" class="">MSVC   (n/a): always >60k ms</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Takeaways:</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">1. Clang performs constant evaluation 10-50 times slower than GCC.</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">2. While Clang performs B ~3 times slower than it performs A, it is not clear that GCC is likewise affected by having to dig through subobjects (if it is, the effect is slight).</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">Questions:</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">1. What am I missing?  Are there flags which might improve clang’s performance?  Is GCC somehow gaining an unfair advantage?  (Potential clue: note that the executable is the same small size, 218 bytes, for each of clang’s results, but it is larger and differs for GCC’s results…meaningful?)  </div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">2. Given the "constexpr all the things" zeitgeist, and the constant evaluation speeds GCC has apparently realized, should the design of ExprConstant.cpp/APValue/etc. be reconsidered?</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">3. If ExprConstant.cpp etc were overhauled for optimal speed, will it still ultimately be true that programs which dig through subobjects of compile time objects are necessarily slower than equivalent programs which deal only with complete compile-time objects?</div><div class=""><br class=""></div><div class="">Not a pressing matter, but maybe worthy of some thought.  Thanks,</div><div class=""><br class=""></div><div class="">Dave</div></body></html>