-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Improve TimeSpan.ToString/TryFormat throughput for default format #18990
Conversation
| { | ||
| charsWritten = sb.Length; | ||
| sb.CopyTo(0, destination, sb.Length); | ||
| charsWritten = sb.Length; |
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.
I am curious, why re-order these lines?
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.
No great reason, just that since it's trivial to do either way, seemed better to only write the number of chars once they'd actually already been written. It doesn't really matter.
| } | ||
|
|
||
| // Standard formats | ||
| // Standard formats other than 'c'/'t'/'T', which should have already been handled. |
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.
Debug.Assert?
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.
We throw below. That seemed sufficient.
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.
Yep. Makes sense.
| { | ||
| int effectiveDigits = literal.ff; | ||
| while (effectiveDigits > 0) | ||
| while (effectiveDigits > 0 && fraction % 10 == 0) |
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.
We use mod here and division within the loop. Would using DivRem be faster?
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.
Would using DivRem be faster?
It would require measuring. I didn't do any substantive changes to this G-formatting code, though, only minor cleanup.
db52f29 to
14b4f9f
Compare
| { | ||
| requiredOutputLength = 9; // requiredOutputLength + 1 for the leading '-' sign | ||
| ticks = -ticks; | ||
| if (ticks < 0) |
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 second if (ticks < 0) is always false, isn't it?
if ticks is less than a zero then ticks = -ticks make it more than zero.
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 second if (ticks < 0) is always false, isn't it?
No. -long.MinValue == long.MinValue.
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 for an answer. Pretty interesting that the same applies to int.MinValue == -int.MinValue, but not to sbyte and short.
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.
That is because all arithmetic operations on types smaller than int are automatically promoted to int beforehand, see here.
Improves the throughput of the null/"c"/"t"/"T" default format for TimeSpan.ToString/TryFormat, porting over the approach/specialization from Utf8Formatter.
Contributes to https://github.com/dotnet/corefx/issues/30612
cc: @jkotas, @danmosemsft, @ahsonkhan
Benchmark:
Before/After: