Skip to content

Commit

Permalink
make few methods used by DateTime.UtcNow inlinable to minimize the le…
Browse files Browse the repository at this point in the history
…ap second performance regression impact, related to #25728
  • Loading branch information
adamsitnik committed Aug 7, 2019
1 parent e72ac90 commit 65899e3
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 14 deletions.
33 changes: 20 additions & 13 deletions src/System.Private.CoreLib/shared/System/DateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -641,32 +641,38 @@ public int CompareTo(DateTime value)

// Returns the tick count corresponding to the given year, month, and day.
// Will check the if the parameters are valid.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long DateToTicks(int year, int month, int day)
{
if (year >= 1 && year <= 9999 && month >= 1 && month <= 12)
if (year < 1 || year > 9999 || month < 1 || month > 12 || day < 1)
{
int[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
if (day >= 1 && day <= days[month] - days[month - 1])
{
int y = year - 1;
int n = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
return n * TicksPerDay;
}
ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay();
}

int[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
if (day > days[month] - days[month - 1])
{
ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay();
}
throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);

int y = year - 1;
int n = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
return n * TicksPerDay;
}

// Return the tick count corresponding to the given hour, minute, second.
// Will check the if the parameters are valid.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long TimeToTicks(int hour, int minute, int second)
{
//TimeSpan.TimeToTicks is a family access function which does no error checking, so
//we need to put some error checking out here.
if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60)
{
return (TimeSpan.TimeToTicks(hour, minute, second));
ThrowHelper.ThrowArgumentOutOfRange_BadHourMinuteSecond();
}
throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);

return (TimeSpan.TimeToTicks(hour, minute, second));
}

// Returns the number of days in the month given by the year and
Expand Down Expand Up @@ -1182,11 +1188,12 @@ public int Year
// Checks whether a given year is a leap year. This method returns true if
// year is a leap year, or false if not.
//
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsLeapYear(int year)
{
if (year < 1 || year > 9999)
{
throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
ThrowHelper.ThrowArgumentOutOfRange_Year();
}
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
Expand Down
31 changes: 31 additions & 0 deletions src/System.Private.CoreLib/shared/System/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,31 @@ internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
ExceptionResource.ArgumentOutOfRange_Count);
}

[DoesNotReturn]
internal static void ThrowArgumentOutOfRange_Year()
{
throw GetArgumentOutOfRangeException(ExceptionArgument.year,
ExceptionResource.ArgumentOutOfRange_Year);
}

[DoesNotReturn]
internal static void ThrowArgumentOutOfRange_BadYearMonthDay()
{
throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
}

[DoesNotReturn]
internal static void ThrowArgumentOutOfRange_BadHourMinuteSecond()
{
throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
}

[DoesNotReturn]
internal static void ThrowArgumentOutOfRange_TimeSpanTooLong()
{
throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
}

[DoesNotReturn]
internal static void ThrowWrongKeyTypeArgumentException<T>(T key, Type targetType)
{
Expand Down Expand Up @@ -657,6 +682,8 @@ private static string GetArgumentName(ExceptionArgument argument)
return "elementType";
case ExceptionArgument.arrayIndex:
return "arrayIndex";
case ExceptionArgument.year:
return "year";
default:
Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum.");
return "";
Expand Down Expand Up @@ -687,6 +714,8 @@ private static string GetResourceString(ExceptionResource resource)
return SR.ArgumentOutOfRange_IndexCountBuffer;
case ExceptionResource.ArgumentOutOfRange_Count:
return SR.ArgumentOutOfRange_Count;
case ExceptionResource.ArgumentOutOfRange_Year:
return SR.ArgumentOutOfRange_Year;
case ExceptionResource.Arg_ArrayPlusOffTooSmall:
return SR.Arg_ArrayPlusOffTooSmall;
case ExceptionResource.NotSupported_ReadOnlyCollection:
Expand Down Expand Up @@ -901,6 +930,7 @@ internal enum ExceptionArgument
endIndex,
elementType,
arrayIndex,
year,
}

//
Expand All @@ -912,6 +942,7 @@ internal enum ExceptionResource
ArgumentOutOfRange_IndexCount,
ArgumentOutOfRange_IndexCountBuffer,
ArgumentOutOfRange_Count,
ArgumentOutOfRange_Year,
Arg_ArrayPlusOffTooSmall,
NotSupported_ReadOnlyCollection,
Arg_RankMultiDimNotSupported,
Expand Down
4 changes: 3 additions & 1 deletion src/System.Private.CoreLib/shared/System/TimeSpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Globalization;
using System.Runtime.CompilerServices;

namespace System
{
Expand Down Expand Up @@ -288,13 +289,14 @@ public static TimeSpan FromTicks(long value)
return new TimeSpan(value);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static long TimeToTicks(int hour, int minute, int second)
{
// totalSeconds is bounded by 2^31 * 2^12 + 2^31 * 2^8 + 2^31,
// which is less than 2^44, meaning we won't overflow totalSeconds.
long totalSeconds = (long)hour * 3600 + (long)minute * 60 + (long)second;
if (totalSeconds > MaxSeconds || totalSeconds < MinSeconds)
throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
ThrowHelper.ThrowArgumentOutOfRange_TimeSpanTooLong();
return totalSeconds * TicksPerSecond;
}

Expand Down

0 comments on commit 65899e3

Please sign in to comment.