Skip to content

Commit

Permalink
Preallocate the TimeZoneInfo.Utc instance (dotnet/coreclr#8530)
Browse files Browse the repository at this point in the history
There doesn't appear to be a good reason why the TimeZoneInfo.Utc
instance needs to be cleared when TimeZoneInfo.ClearCachedData() is
called. Instead, we can pre-allocate and reuse a singleton instance,
obviating the need for the lazy-initialization/locking mechanics.

Commit migrated from dotnet/coreclr@23422d6
  • Loading branch information
justinvp authored and tarekgh committed Dec 9, 2016
1 parent aaf8060 commit addfecb
Showing 1 changed file with 13 additions and 37 deletions.
50 changes: 13 additions & 37 deletions src/coreclr/src/mscorlib/src/System/TimeZoneInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ private enum TimeZoneInfoResult {
private const long c_ticksPerDay = c_ticksPerHour * 24;
private const long c_ticksPerDayRange = c_ticksPerDay - c_ticksPerMillisecond;

private static readonly TimeZoneInfo s_utcTimeZone = CreateCustomTimeZone(c_utcId, TimeSpan.Zero, c_utcId, c_utcId);

//
// All cached data are encapsulated in a helper class to allow consistent view even when the data are refreshed using ClearCachedData()
//
Expand All @@ -125,7 +127,6 @@ private enum TimeZoneInfoResult {
class CachedData
{
private volatile TimeZoneInfo m_localTimeZone;
private volatile TimeZoneInfo m_utcTimeZone;

private TimeZoneInfo CreateLocal()
{
Expand Down Expand Up @@ -163,31 +164,6 @@ private TimeZoneInfo CreateLocal()
}
}

private TimeZoneInfo CreateUtc()
{
lock (this)
{
TimeZoneInfo timeZone = m_utcTimeZone;
if (timeZone == null) {
timeZone = CreateCustomTimeZone(c_utcId, TimeSpan.Zero, c_utcId, c_utcId);
m_utcTimeZone = timeZone;
}
return timeZone;
}
}

public TimeZoneInfo Utc {
get {
Contract.Ensures(Contract.Result<TimeZoneInfo>() != null);

TimeZoneInfo timeZone = m_utcTimeZone;
if (timeZone == null) {
timeZone = CreateUtc();
}
return timeZone;
}
}

//
// GetCorrespondingKind-
//
Expand Down Expand Up @@ -215,7 +191,7 @@ private TimeZoneInfo CreateUtc()
// in this example. Only when the user passes in TimeZoneInfo.Local or
// TimeZoneInfo.Utc to the ConvertTime(...) methods will this check succeed.
//
if ((object)timeZone == (object)m_utcTimeZone) {
if ((object)timeZone == (object)s_utcTimeZone) {
kind = DateTimeKind.Utc;
}
else if ((object)timeZone == (object)m_localTimeZone) {
Expand Down Expand Up @@ -427,7 +403,7 @@ private AdjustmentRule[] GetFilledRules()
}
else if (dateTime.Kind == DateTimeKind.Utc) {
CachedData cachedData = s_cachedData;
adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, TimeZoneInfoOptions.None, cachedData);
adjustedTime = TimeZoneInfo.ConvertTime(dateTime, s_utcTimeZone, this, TimeZoneInfoOptions.None, cachedData);
}
else {
adjustedTime = dateTime;
Expand Down Expand Up @@ -525,7 +501,7 @@ private AdjustmentRule GetPreviousAdjustmentRule(AdjustmentRule rule)
//
// normal case of converting from Local to Utc and then getting the offset from the UTC DateTime
//
DateTime adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags);
DateTime adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags);
return GetUtcOffsetFromUtc(adjustedTime, this);
}

Expand Down Expand Up @@ -592,7 +568,7 @@ private AdjustmentRule GetPreviousAdjustmentRule(AdjustmentRule rule)
}
else if (dateTime.Kind == DateTimeKind.Utc) {
CachedData cachedData = s_cachedData;
adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, flags, cachedData);
adjustedTime = TimeZoneInfo.ConvertTime(dateTime, s_utcTimeZone, this, flags, cachedData);
}
else {
adjustedTime = dateTime;
Expand Down Expand Up @@ -759,7 +735,7 @@ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String s
// be reference equal to the new TimeZoneInfo.Utc
//
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, cachedData.Utc, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData);
return ConvertTime(dateTime, s_utcTimeZone, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData);
}
else
{
Expand Down Expand Up @@ -809,7 +785,7 @@ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String s
}
CachedData cachedData = s_cachedData;
if (dateTime.Kind == DateTimeKind.Utc) {
return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
return ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
}
else {
return ConvertTime(dateTime, cachedData.Local, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
Expand Down Expand Up @@ -903,7 +879,7 @@ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String s
//
static public DateTime ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone) {
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
return ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
}


Expand All @@ -917,7 +893,7 @@ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String s
return dateTime;
}
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, TimeZoneInfoOptions.None, cachedData);
return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData);
}


Expand All @@ -926,12 +902,12 @@ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String s
return dateTime;
}
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags, cachedData);
return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags, cachedData);
}

static public DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone) {
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, sourceTimeZone, cachedData.Utc, TimeZoneInfoOptions.None, cachedData);
return ConvertTime(dateTime, sourceTimeZone, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData);
}


Expand Down Expand Up @@ -1156,7 +1132,7 @@ private static void PopulateAllSystemTimeZones(CachedData cachedData)
static public TimeZoneInfo Utc {
get {
Contract.Ensures(Contract.Result<TimeZoneInfo>() != null);
return s_cachedData.Utc;
return s_utcTimeZone;
}
}

Expand Down

0 comments on commit addfecb

Please sign in to comment.