Skip to content

DateTime.Now / DateTime.Today / ... impacts Android startup #81890

Open
@tipa

Description

@tipa

Description

I am using DateTime.Now, DateTimeOffset.Now and DateTime.Today frequently in my app (I think many apps do).
Being aware that adding the timezone data to the DateTime/Offset structures comes with a performance penalty, I am trying to avoid them as much as possible and am using DateTime.UtcNow & DateTimeOffset.UtcNow instead. However, this is not always possible. On Android particularly, loading the time zone can significantly slow down startup performance and there has been work done before here to mitigate this problem: #71004

Data

Using this script and an empty Android .NET7 project I did some startup benchmarks. I started with an empty .NET for Android template.

  1. Added Task.Delay(400).Wait(); to simulate startup work - no other changes: 713 ms
  2. + _ = DateTime.Now to the MainActivity: 793 ms
  3. + _ = Task.Run(() => _ = DateTime.Today); to MainApplication.OnCreate: 714 ms

Tests were done on a Samsung A52.
Demo project used: AndroidApp.zip

Analysis

There is still a performance penalty (~70ms) when using timezone-dependent time during app startup. It can be mitigated by triggering the timezone info retrieval process early in the startup process on a different thread.

Would it be possible to trigger this process automatically during app startup so the timezone information is available immediately the first DateTimeOffset.Now et al is called?

Also, if DateTime.Today is called, the timezone offset does not need to be known. It can be calculated very fast (~1-2ms) using Android APIs:

ar cal = Java.Util.Calendar.Instance;
var today = new DateTime(
    cal.Get(Java.Util.CalendarField.Year),
    cal.Get(Java.Util.CalendarField.Month) + 1,
    cal.Get(Java.Util.CalendarField.DayOfMonth));

Would it be possible to calculate & cache a DateTime.Today-placeholder using the code above and return it from DateTime.Today-calls it while the timezone file is loaded and parsed in the background? That way I could use a penalty-free DateTime.Today right away when starting the app.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions