-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[release/7.0] [Android][libs] Introduce DateTimeOffset.Now temporary …
…fast result (#74965) Backport of #74459 to release/7.0 Introduces fast path for DateTimeOffset.Now on Android that allows us to load tzdata in the background. This improves performance from around 227ms to 21.81ms.
- Loading branch information
1 parent
e8649de
commit 54e978c
Showing
7 changed files
with
115 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.Android.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Threading; | ||
|
||
namespace System | ||
{ | ||
public readonly partial struct DateTimeOffset | ||
{ | ||
// 0 == in process of being loaded, 1 == loaded | ||
private static volatile int s_androidTZDataLoaded = -1; | ||
|
||
// Now on Android does the following | ||
// 1) quickly returning a fast path result when first called if the right AppContext data element is set | ||
// 2) starting a background thread to load TimeZoneInfo local cache | ||
// | ||
// On Android, loading AndroidTZData is expensive for startup performance. | ||
// The fast result relies on `System.TimeZoneInfo.LocalDateTimeOffset` being set | ||
// in the App Context's properties as the appropriate local date time offset from UTC. | ||
// monovm_initialize(_preparsed) can be leveraged to do so. | ||
// However, to handle timezone changes during the app lifetime, AndroidTZData needs to be loaded. | ||
// So, on first call, we return the fast path and start a background thread to load | ||
// the TimeZoneInfo Local cache implementation which loads AndroidTZData. | ||
public static DateTimeOffset Now | ||
{ | ||
get | ||
{ | ||
DateTime utcDateTime = DateTime.UtcNow; | ||
|
||
if (s_androidTZDataLoaded == 1) // The background thread finished, the cache is loaded. | ||
{ | ||
return ToLocalTime(utcDateTime, true); | ||
} | ||
|
||
object? localDateTimeOffset = AppContext.GetData("System.TimeZoneInfo.LocalDateTimeOffset"); | ||
if (localDateTimeOffset == null) // If no offset property provided through monovm app context, default | ||
{ | ||
// no need to create the thread, load tzdata now | ||
s_androidTZDataLoaded = 1; | ||
return ToLocalTime(utcDateTime, true); | ||
} | ||
|
||
// The cache isn't loaded yet. | ||
if (Interlocked.CompareExchange(ref s_androidTZDataLoaded, 0, -1) == -1) | ||
{ | ||
new Thread(() => | ||
{ | ||
try | ||
{ | ||
// Delay the background thread to avoid impacting startup, if it still coincides after 1s, startup is already perceived as slow | ||
Thread.Sleep(1000); | ||
|
||
_ = TimeZoneInfo.Local; // Load AndroidTZData | ||
} | ||
finally | ||
{ | ||
s_androidTZDataLoaded = 1; | ||
} | ||
}) { IsBackground = true }.Start(); | ||
} | ||
|
||
// Fast path obtained offset incorporated into ToLocalTime(DateTime.UtcNow, true) logic | ||
int localDateTimeOffsetSeconds = Convert.ToInt32(localDateTimeOffset); | ||
TimeSpan offset = TimeSpan.FromSeconds(localDateTimeOffsetSeconds); | ||
long localTicks = utcDateTime.Ticks + offset.Ticks; | ||
if (localTicks < DateTime.MinTicks || localTicks > DateTime.MaxTicks) | ||
throw new ArgumentException(SR.Arg_ArgumentOutOfRangeException); | ||
|
||
return new DateTimeOffset(localTicks, offset); | ||
} | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.NonAndroid.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace System | ||
{ | ||
public readonly partial struct DateTimeOffset | ||
{ | ||
// Returns a DateTimeOffset representing the current date and time. The | ||
// resolution of the returned value depends on the system timer. | ||
public static DateTimeOffset Now => ToLocalTime(DateTime.UtcNow, true); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters