--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
It looks like https://groups.google.com/a/chromium.org/d/topic/chromium-dev/QEpKyLOQvQY/discussion
has the conclusion of the "Faster Builds Task Force", but not a record
of their discussions. Enforcement dates to the initial checkin of the
clang plugin: http://codereview.chromium.org/6368055.
If the problem is the time spent to emit definitions into every
translation unit, we can solve that by requiring that every class have
a "key function". A class's key function is "the first non-pure
virtual function that is not inline at the point of class definition"
(https://mentorembedded.github.io/cxx-abi/abi.html#vague-vtable). When
classes don't have a key function, their vtable and all inline virtual
functions (including empty ones) are emitted in every compilation unit
that uses the class. Requiring that non-empty virtual functions be
non-inline probably increased the number of key functions in the
codebase, which sped up builds, but we could do better by matching the
rule the compiler uses.
There's also some cost to parsing long inline definitions, but that
wouldn't be constrained to virtual functions, and doesn't apply much
to the sort of short inline definitions that improve readability.
is defined in the .cc file."The rule would be, "if you have virtual methods, make sure at least 1
On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org> wrote:is defined in the .cc file."The rule would be, "if you have virtual methods, make sure at least 1I think that's still too complicated, and way too easy to do the wrong thing with when refactoring code. It's also far easier to review changes and simply say "don't do that" when seeing an inline virtual rather than going and looking to see if there's some other virtual that's non-inline.
Also, the recommendations here were not just for faster builds; IIRC we got both binary size and performance wins from reducing the amount of inlining we were doing. Neither build speed nor binary size are significant factors in google3, which is part of why it's plausible that this rule should actually differ for Chromium.I'm in favor of leaving the rule as-is.
On Tue, Nov 17, 2015 at 12:13 AM, Peter Kasting <pkas...@chromium.org> wrote:
> On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org>
> wrote:
>>
>> The rule would be, "if you have virtual methods, make sure at least 1
>> is defined in the .cc file."
>
>
> I think that's still too complicated, and way too easy to do the wrong thing
> with when refactoring code. It's also far easier to review changes and
> simply say "don't do that" when seeing an inline virtual rather than going
> and looking to see if there's some other virtual that's non-inline.
Review effort is irrelevant when there's a clang plugin enforcing the
rule. The violation won't survive to the code review.
> Also, the recommendations here were not just for faster builds; IIRC we got
> both binary size and performance wins from reducing the amount of inlining
> we were doing.
The "no inlined virtuals" rule is justified in
http://www.chromium.org/developers/coding-style/cpp-dos-and-donts#TOC-Stop-inlining-virtual-methods
as "You can't inline virtual methods under most circumstances". So why
do you think adding a second level of inlining-prevention for virtuals
helps binary size?
> Neither build speed nor binary size are significant factors
> in google3, which is part of why it's plausible that this rule should
> actually differ for Chromium.
Icache use is a significant factor for google3, which is how reducing
inlining helped performance in Chrome. Jeff Dean's been known to
un-inline chunks of core google3 library code in order to improve his
programs' performance. Chrome is not a unique snowflake in this
regard.
Jeffrey
Also, the recommendations here were not just for faster builds; IIRC we got both binary size and performance wins from reducing the amount of inlining we were doing. Neither build speed nor binary size are significant factors in google3, which is part of why it's plausible that this rule should actually differ for Chromium.
I've not actually seen any numbers about the impact of this restriction. Do we have any data?
On Tue, Nov 17, 2015 at 12:13 AM, Peter Kasting <pkas...@chromium.org> wrote:
> On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org>
> wrote:
>>
>> The rule would be, "if you have virtual methods, make sure at least 1
>> is defined in the .cc file."
>
>
> I think that's still too complicated, and way too easy to do the wrong thing
> with when refactoring code. It's also far easier to review changes and
> simply say "don't do that" when seeing an inline virtual rather than going
> and looking to see if there's some other virtual that's non-inline.
Review effort is irrelevant when there's a clang plugin enforcing the
rule. The violation won't survive to the code review.
Icache use is a significant factor for google3, which is how reducing
inlining helped performance in Chrome. Jeff Dean's been known to
un-inline chunks of core google3 library code in order to improve his
programs' performance. Chrome is not a unique snowflake in this
regard.
On Tue, Nov 17, 2015 at 7:48 AM, Jeffrey Yasskin <jyas...@chromium.org> wrote:On Tue, Nov 17, 2015 at 12:13 AM, Peter Kasting <pkas...@chromium.org> wrote:
> On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org>
> wrote:
>>
>> The rule would be, "if you have virtual methods, make sure at least 1
>> is defined in the .cc file."
>
>
> I think that's still too complicated, and way too easy to do the wrong thing
> with when refactoring code. It's also far easier to review changes and
> simply say "don't do that" when seeing an inline virtual rather than going
> and looking to see if there's some other virtual that's non-inline.
Review effort is irrelevant when there's a clang plugin enforcing the
rule. The violation won't survive to the code review.We don't yet run clang on all our platforms (e.g. Windows, where I do all my work). Any code compiled only on non-clang platforms won't get this benefit. (Yes, I actually do work with Windows-only code not infrequently.)
Also, even with a clang plugin, I think it is still easier to write and review code with the simple rule "don't inline virtuals" than with a more complicated set of guidelines and considerations. And it leads to more consistent code; I can think of plenty of cases where a plausible thing to do, if we allowed inlined virtuals, would be to inline all the methods:class SomethingDelegate {// Override these if you need to handle any of these events.virtual void OnAction1() {}virtual bool OnAction2() { return false; }virtual int OnAction3() { return 0; }};With the "key function" rule, we force people to go back and decide which of these methods to de-inline. Then some are inline and some aren't. Now future readers of the header file may assume the de-inlined function is more complicated or that there's some particular reason for this difference beyond just "make the compiler happy". This kind of inconsistency is IMO not to be taken lightly.
Icache use is a significant factor for google3, which is how reducing
inlining helped performance in Chrome. Jeff Dean's been known to
un-inline chunks of core google3 library code in order to improve his
programs' performance. Chrome is not a unique snowflake in this
regard.This is an argument that caution is needed when inlining, not only in Chrome but in Google code. You're effectively arguing that the Google style rule needs to urge more caution than it does. I don't see that as an argument for relaxing Chrome's rules; much easier to say "don't do this" than "maybe you can do this but be careful because there are subtle performance implications you likely won't notice".In any case, if you're proposing relaxing the rules, I think the burden would be on you to show that neither build times nor performance would suffer. We're making assumptions in this thread about why this rule was put in place and what the effects of relaxing it would be. That doesn't fill me with confidence.Incidentally, part of why I'm pushing back is not only that I think the cost here is non-negligible, but because I think the benefit _is_ negligible. I see the readability gain here as minimal to none (which clearly you do not), so given the variety of possible costs above I don't feel like slogging through this is worth it.PK
--
On Tue, Nov 17, 2015 at 12:00 PM Peter Kasting <pkas...@chromium.org> wrote:On Tue, Nov 17, 2015 at 7:48 AM, Jeffrey Yasskin <jyas...@chromium.org> wrote:On Tue, Nov 17, 2015 at 12:13 AM, Peter Kasting <pkas...@chromium.org> wrote:
> On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org>
> wrote:
>>
>> The rule would be, "if you have virtual methods, make sure at least 1
>> is defined in the .cc file."
>
>
> I think that's still too complicated, and way too easy to do the wrong thing
> with when refactoring code. It's also far easier to review changes and
> simply say "don't do that" when seeing an inline virtual rather than going
> and looking to see if there's some other virtual that's non-inline.
Review effort is irrelevant when there's a clang plugin enforcing the
rule. The violation won't survive to the code review.We don't yet run clang on all our platforms (e.g. Windows, where I do all my work). Any code compiled only on non-clang platforms won't get this benefit. (Yes, I actually do work with Windows-only code not infrequently.)Though it's not perfect, we do have FYI bots that build win clang. I know that the Windows clang devs frequently make patches or file bugs to track new breakage. So it's not as if it would go completely unnoticed. I expect this situation will continue to improve in the future (e.g. win clang would become part of the CQ/waterfall).
With the "key function" rule, we force people to go back and decide which of these methods to de-inline. Then some are inline and some aren't. Now future readers of the header file may assume the de-inlined function is more complicated or that there's some particular reason for this difference beyond just "make the compiler happy". This kind of inconsistency is IMO not to be taken lightly.If the proposed rule change were in effect, I would probably just ask the developer to out-of-line define a virtual destructor.
On Tue, Nov 17, 2015 at 7:48 AM, Jeffrey Yasskin <jyas...@chromium.org> wrote:On Tue, Nov 17, 2015 at 12:13 AM, Peter Kasting <pkas...@chromium.org> wrote:
> On Mon, Nov 16, 2015 at 8:50 PM, Jeffrey Yasskin <jyas...@chromium.org>
> wrote:
>>
>> The rule would be, "if you have virtual methods, make sure at least 1
>> is defined in the .cc file."
>
>
> I think that's still too complicated, and way too easy to do the wrong thing
> with when refactoring code. It's also far easier to review changes and
> simply say "don't do that" when seeing an inline virtual rather than going
> and looking to see if there's some other virtual that's non-inline.
Review effort is irrelevant when there's a clang plugin enforcing the
rule. The violation won't survive to the code review.
We don't yet run clang on all our platforms (e.g. Windows, where I do all my work). Any code compiled only on non-clang platforms won't get this benefit. (Yes, I actually do work with Windows-only code not infrequently.)
Also, even with a clang plugin, I think it is still easier to write and review code with the simple rule "don't inline virtuals" than with a more complicated set of guidelines and considerations. And it leads to more consistent code; I can think of plenty of cases where a plausible thing to do, if we allowed inlined virtuals, would be to inline all the methods:class SomethingDelegate {// Override these if you need to handle any of these events.virtual void OnAction1() {}virtual bool OnAction2() { return false; }virtual int OnAction3() { return 0; }};With the "key function" rule, we force people to go back and decide which of these methods to de-inline. Then some are inline and some aren't. Now future readers of the header file may assume the de-inlined function is more complicated or that there's some particular reason for this difference beyond just "make the compiler happy". This kind of inconsistency is IMO not to be taken lightly.Icache use is a significant factor for google3, which is how reducing
inlining helped performance in Chrome. Jeff Dean's been known to
un-inline chunks of core google3 library code in order to improve his
programs' performance. Chrome is not a unique snowflake in this
regard.This is an argument that caution is needed when inlining, not only in Chrome but in Google code. You're effectively arguing that the Google style rule needs to urge more caution than it does. I don't see that as an argument for relaxing Chrome's rules; much easier to say "don't do this" than "maybe you can do this but be careful because there are subtle performance implications you likely won't notice".In any case, if you're proposing relaxing the rules, I think the burden would be on you to show that neither build times nor performance would suffer. We're making assumptions in this thread about why this rule was put in place and what the effects of relaxing it would be. That doesn't fill me with confidence.Incidentally, part of why I'm pushing back is not only that I think the cost here is non-negligible, but because I think the benefit _is_ negligible. I see the readability gain here as minimal to none (which clearly you do not), so given the variety of possible costs above I don't feel like slogging through this is worth it.PK
--
I think key functions aren't a thing on Windows, so having key functions is less useful there (the vtable goes into every translation unit).Before talking about changing this, it'd probably make sense to make sure build speed etc wouldn't regress.
What other measurements do folks think are relevant?
At this point in the thread, I think it's worth reiterating the original motivation for this change, as that seems to have been buried under the discussion of build times, binary size, performance, etc.:Inlining the definition of trivial methods can make code significantly more readable.
On Tue, Nov 24, 2015 at 11:45 AM, Stefan Zager <sza...@google.com> wrote:At this point in the thread, I think it's worth reiterating the original motivation for this change, as that seems to have been buried under the discussion of build times, binary size, performance, etc.:Inlining the definition of trivial methods can make code significantly more readable.
I don't know how to discuss this in a constructive manner so I was hoping to avoid bikeshedding. "It's more readable!" "No it's not, it's less!" "No it's not!"If instead we find that on Windows we take a build time hit, that's a bit easier to debate.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
If others feel as you do -- that it harms readability rather than helps -- then Jeffrey doesn't have to waste his time running experiments the results of which will make not one bit of difference, and we can end the torturous discussion of the minutiae of build time, performance, key methods, etc.
--
Given that the current rule doesn't match reality on any platform, we should change it in some direction. Either no virtual functions should be inline, or small non-empty virtual inlines should be allowed.
My ancient and unreliable recollection is that VC++ doesn't use a "key" function to decide when to generate the vtable (and hence the inline virtual functions), it instead does that generation in any translation unit that creates an object of that type. So, the cost is likely to be proportional to the number of translation units creating that type (or that that contain or derive from it) which in most cases will be fairly modest.I have not validated this vague memory but I thought I'd mention it in case it informed any tests that might be run.
This points at the other way to guarantee a vtable is only generated in 1 .o file: make the constructors or creation functions out-of-line:
On Wed, Nov 25, 2015 at 2:34 PM, Jeffrey Yasskin <jyas...@chromium.org> wrote:This points at the other way to guarantee a vtable is only generated in 1 .o file: make the constructors or creation functions out-of-line:The destructor may also reference the vtable, so you'd want to make sure you move that out of line as well. I think Chromium already encourages this to reduce code size.This is a foolproof way to avoid duplicate vtables and code in object files, but it will also block the (not very good) devirtualization transformations LLVM currently has. They are currently built around the idea of forwarding vptr stores to vptr loads, and if you hide the vptr store, we're hosed.That said, moving ctors/dtors of polymorphic classes out of line is probably the Right Thing To Do. The fact that LLVM can't devirtualize here is just a missed optimization. Using LTO (LTCG by another name) will make it work today. Last summer we had a intern work on devirtualization that doesn't depend on constructor inlining, but his prototype doesn't work on classes with inline virtual methods. :(
Note that moving constructors and destructors out of line makes them more expensive since calling the super constructor/destructor then becomes a non-inline function call, that's probably sensible as the default, but we should have a way to explicitly use an inline super call as well.
On Thu, 26 Nov 2015 05:16:32 +0100, Elliott Sprehn <esp...@chromium.org> wrote:Note that moving constructors and destructors out of line makes them more expensive since calling the super constructor/destructor then becomes a non-inline function call, that's probably sensible as the default, but we should have a way to explicitly use an inline super call as well.I think that is more in the line of "may make them more expensive". With inlining numerous parameters like instruction cache contents, call costs, code layout, code size and several more will determine what alternative is faster and what is slower. And what alternative is smaller and what is larger.
At the moment, I'm thinking of extending the "out-line your constructors and destructors" rule (https://code.google.com/p/chromium/codesearch/#chromium/src/tools/clang/plugins/FindBadConstructsConsumer.cpp&l=258-275) to include the number of inline virtual member functions as a cost for leaf classes.
- I'd identify a leaf class as having no pure virtual methods and a non-protected constructor.
- If a class has any virtual members, I'd add 3 + the number of inline virtual members to ctor_score, and if the destructor is non-virtual, the same to dtor_score.
Users would get the "Complex class/struct needs an explicit out-of-line constructor." or "Complex class/struct needs an explicit out-of-line destructor." error instead of anything specifically about virtual functions. We could word-smith that, or special-case when inlined virtuals pushed it over the edge, or just let folks out-of-line their constructors instead of their methods.Thoughts?