-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Document the use of non-short-circuiting |
operator in Char::IsAsciiLetterOrDigit
#102547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The JIT is able to optimize this case because the functions in two branches are trivial.
|
This is intentional, see https://github.com/dotnet/runtime/pull/69318/files#r872595998 |
Ah, I see. Thanks for clarifying! Maybe we should add a comment so that we don't keep revisiting this? |
In my opinion it does warrant a comment so people don't need to pull out sharplab/disasmo to check why it's like this 😆 I think the rationale here is that the input is not considered to be predictable so we don't try have our stupidly smart modern branch predictors predict it(?). If one case is more common the checks could be ordered and the other version could be tiny bit faster (I think this sorta cmov data-dependecy issue vs a branch in a loop.. but kinda not as the current version doesn't even need conditional mov so it's even better like this..) Also the IL is much nicer for the importer in the branchless version. |
In this case, branching itself has more overhead than evaluating either branch. This can be a common sense of advanced optimization, but sometimes I can't notice it. |
Thanks! I'll convert this PR into just a PR to add an explanatory comment. |
||
operator in Char::IsAsciiLetterOrDigit
|
operator in Char::IsAsciiLetterOrDigit
|
operator in Char::IsAsciiLetterOrDigit
|
operator in Char::IsAsciiLetterOrDigit
// Use of the non-short-circuiting logical OR operator (|) here is an intentional optimization. | ||
// It avoids a low-level branch instruction. (In other words, the overhead of branching | ||
// is greater than the cost of simply executing IsBetween.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment looks too verbose for users who can understand it. The position is also questionable with xml doc.
I'd suggest a trailing comment on the same line, just saying "use arithmetic or to avoid branching" or similar.
Tests seem to be failing for an unrelated reason. (In the end, all I did was add a comment.) I don't seem to have permission to schedule a retry of the tests. Any advice would be appreciated. |
/// 'a' through 'z', inclusive, or '0' through '9', inclusive. | ||
/// </remarks> | ||
public static bool IsAsciiLetterOrDigit(char c) => IsAsciiLetter(c) | IsBetween(c, '0', '9'); | ||
public static bool IsAsciiLetterOrDigit(char c) => IsAsciiLetter(c) | IsBetween(c, '0', '9'); // Using | here is an optimization (avoids branching). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. There are a variety of places we use |
like this, which is part of its raison d'etre. Why without a comment is there an assumption that it's a mistake and why is this particular use special so as to warrant a dedicated comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I do a quick search through this repo for " | "
, I don't see many instances of |
being used for boolean operations.
If there were hundreds (or even dozens) of similar usage patterns, I'd agree that it's a common-enough practice as to not warrant any clarification.
It seems, however, there are only a few.
The net effect is that the codebase exhibits these occasional inconsistencies. Mentally, when you encounter one, it gives you pause: "Wait. That doesn't look right. Why's that?"
Maybe you remember why it's that way. Maybe you have to jog your memory. Maybe you're stumped. (Most people would be stumped.)
Either way, you've wasted time contemplating it and you're likely to do it all over again when you re-encounter it at some in the future.
A simple comment here short-circuits (pun intended) that whole mental exercise.
If there are indeed only a few such instances within this repo, I'd be happy to amend this PR to cover those as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Personally, I still don't believe this is valuable. The only reason to use a | here is for the exact reason the comment would state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My guess is that most C# programmers aren't even aware that this is valid syntax for a boolean
expression.
If you put yourself in their 👞👞 ...?
Added the following comment to clarify the rationale for using
|
over||
inChar::IsAsciiLetterOrDigit
.