161 karma · joined January 29, 2012
I'm just a little sore about it because it was being sold as a "hey here is an optimization!" and it very much was not, at least from where I was sitting. I thought this was a very very good case of having it be UB (I think the entire class of user source annotations like this should be UB if the runtime behavior violates the user annotation)
I think maybe WG21 was concerned a compiler engineer would be clever if throwing in noexcept were UB, for example and assume any block that throws is unreachable and could just be removed along with all blocks it postdominates. Compiler guys love optimizations that just remove code. The fastest and smallest code is code that can’t run and doesn’t exist
Noexcept on the surface is useful, except for the terminate guarantee, which requires a ton of work to avoid metadata size growth and hurts inlining. If violations of noexcept were UB and it was a pure optimization hint the world would be much better
In reality undefined behavior is useful in the sense that (like this case) it allows us to not have to write code to consider and handle certain situations - code which may make all situations slower, or allows certain optimizations to exist which work 99% of the time.
Regarding “not pan out”: I think the overhead of noexcept for the single function call case is fine, and inlining is and has always been the issue.
“Zero overhead” refers to the actual functions code gen; there are still tables and stuff that have to be updated
Our implementation of noexcept for the single function case I think is fine now. There is a single extra bit in the exception function info which is checked by the unwinder. Other than requiring exception info in cases where we otherwise wouldn’t
The inlining case has always been both more complicated and more of a problem. If your language feature inhibits inlining in any situation you have a real problem
https://github.com/TriangleCppDevelopersGroup/TerryMahaffeyC...
*edit except the stuff about fastlink
*edit 2 also I have since added a heuristic bonus for the "inline" keyword because I could no longer stand the irony of "inline" not having anything to do with inlining
*edit 3 ok, also statements like "consider doing X if you have no security exposure" haven't held up well
In LTCG (MSVC)/O3 (GCC/Clang) there are prepasses over the entire callgraph to collect this order
Specifically here (as I said in other comments) where it goes from complicated/quality of implementation issue to "shit this is complicated" is when you consider inlining. If noexcept inhibits inlining in any conceivable circumstances then it's having a dramatic (slightly indirect) impact on performance
The inlining case was always the hard problem to solve though
I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost
The reason is simple: there is a guarantee here that noexcept functions don't throw. std::terminate has to be called. That has to be implemented. There is some cost to that - conceptually every noexcept function (or worse, every call to a noexcept function) is surrounded by a giant try/catch(...) block.
Yes there are optimizations here. But it's still not free
Less obvious; how does inlining work? What happens if you inline a noexcept function into a function that allows exceptions? Do we now have "regions" of noexceptness inside that function (answer: yes). How do you implement that? Again, this is implementable, but this is even harder than the whole function case, and a naive/early implementation might prohibit inlining across degrees of noexcept-ness to be correct/as-if. And guess what, this is what early versions of MSVC did, and this was our biggest problem: a problem which grew release after release as noexcept permeated the standard library.
Anyway. My point is, we need more backend compiler engineers on WG21 and not just front end, library, and language lawyer guys.
I argued then that if instead noexcept violations were undefined, we could ignore all this, and instead just treat it as the pure optimization it was being marketed as (ie, help prove a region can't throw, so we can elide entire try/catch blocks etc). The reaction to my suggestion was not positive.
Registers that you name in assembly != physical registers. And when you use a register in two different instructions, you won't necessarily get the same physical register each time.
This is a complex issue, but consider abandoning PGO and just compiling for for speed then. PGO doesn't help in each and every case.
> RE xperf (and WinDbg): Stop bundling this shit in "Toolkits".
How else would you bundle it? It's not simple to put something as part of the base OS image. And I haven't heard about these installers breaking the VS installer - that sounds like a bad bug.
> __assume is so useless. How often does someone write a branch that does nothing every time?
It's commonly used as a retail version of a debug ASSERT macro. But yes, like I said earlier - I wish we would do more with static annotations, but I've gotten push back.
> PogoAutoSweep crashes threaded programs if you don't suspend every other thread but it's still quasi documented. The PogoSafeMode build flag/environment appears to be ignored.
I've never seen PogoAutoSweep crash - do you have a repro? PogoSafeMode doesn't affect PogoAutoSweep, only probe generation.
> The filename postfix that PogoAutoSweep adds breaks the VS2012 PGO menu options.
Haven't heard of this either, but stay tuned. I don't like the PGO menu options as they currently stand.
> There's nothing one can do to limit the VS2012 profiler to specific threads.
I can forward that request to the profiler team.
> The interface for instrumenting specific functions is terrible, use a plain text file or decl_spec FFS.
Are you talking about PGI or an instrumented profiler?
> If there are #defines or other ways to detect an instrumented build, they're terribly documented.
There isn't an easy way, and having different code in the PGI build versus the PGU build would be problematic.
> PGO instrumentation/optimization is woefully obtuse. What did it pick for speed? Why did it pick it? What branches did it fold/unfold?
Stay tuned
> How does the pgc weighting actually work?
The obvious way, the counts are multiplied by the provided factor before being merged in the PGD.
> Can I artificially create my own pgc?
Not realistically.
> Not related to our main response loop, but we can see in our logging threads that the LFH malloc appears to often call RtlAnsiStringToUnicodestring.
No idea (CRT owns malloc, Windows owns LFH).
> Speaking of which, changing the malloc implementation is still horrible even after the VS2010 msvcrt changes. In linux...
I'm not an expert, but my understanding was that malloc and friends were weak symbols, and if you just linked in an obj that defined malloc it would be selected as the "real" malloc without giving an ODR.
> Why is there SemaphoreSlim in C# but not C++? Why is there no Benaphore primitive that can also be used in WaitForMultipleObjects?
I'm not sure, Windows owns this.
> Serious issues in Microsoft Developer Connect are often ignored, closed as behaves as expected, or dismissed off hand
I've heard complaints about MSConnect before as well. All I can say is that it is the correct place to file bugs; and the issues there do directly show up in our bug list (someone goes through connect issues, filters/combines them, and files bugs).
> There is still no valgrind/cachegrind equivalent that provides the same level of detail
That is correct. Sorry.
> Our statically linked application takes 20 minutes link and the link is not parallel. C++ compiles are likewise brutally slow
Link.exe performance is at the top of our minds right now, you're not the only one to bring it up. VS 2013 will have some perf improvements across the FE (to help with C++ being brutally slow) but there is always more to do.
> And no, I'm not going to turn on precompiled headers, MSVC builds incorrect binaries about 5% of the time as it is.
Never heard that before - codegen bugs are always deadly serious and treated with high priority. If you have a repro, please share it.
RE: likely/unlikely, VS has __assume(0), which isn't exactly the same thing I know, but it is something and does help. I'm actually in favor of us doing more with static annotations to bring PGO style optimizations to non-PGO builds. If you feel the same way please be louder about it, but realize there is a vocal group of people who consider static annotations harmful (and they have a large body of evidence in __forceinline backing them up).
oprofile: There is ETW/xperf, and of course a variety of instrumented profilers (both shipping and internal)
Although I do wish my team was larger, and it doesn't get all the love that some of the more flashing UI stuff does, I wouldn't go as far as to say the toolchain is withering. Some of the smartest people I know are working on my team with me on these problems.