DateTime Performance
Unity’s Time
class is an easy way to get the relative time. You can find the time since the app started with Time.time
or the time between frames with Time.deltaTime
. But what if you want to know the absolute time? You may need to display a clock to the user, send a timestamp over a network, or record when a game was saved. This is where System.DateTime
comes in. It’s powerful and offers so much functionality that it’s natural to worry about about how slow it’ll be. So today’s article puts it to the test to find out how much time is being spent in operations like DateTime.Now
which gets the current date and time. Is it quick enough that you shouldn’t worry? Read on to find out.
The docs for DateTime
tell us that it has tons of features. Most programmers stick to a few core functions and that’s what I’ll be testing today.
The first is the static Now
property that returns you a DateTime
representing the current date and time. This has some great advantages over Time.time
. First, it’s not just a snapshot of the time at the start of the frame. It’s actually up to date as of the exact time you call Now
. It also returns you a full DateTime
, meaning you get the absolute date and time, including milliseconds.
Second is the AddSeconds
function, one of the many AddX
functions for advancing the DateTime
by some amount of time. One common use for these is to transform an offset into an actual DateTime
. For example, if you have a UNIX timestamp it is the number of seconds since January 1, 1970. You can make a DateTime
for that date and then call AddSeconds
on it to get the actual date.
Third is the reverse of the AddX
functions: subtracting two DateTime
objects to get a TimeSpan
. This represents the amount of time between them, and it easily queried to see how long that is in seconds, days, and so forth. Given that calendars are really complex and include things like leap years, this is a really easy way to check how much time has really elapsed between two DateTime
instances.
Lastly, DateTime
has an overloaded ToString
that allows you to easily format it into whatever kind of string you’d like. You might want July 20, 2015 to be “07-20-2015”, “20-07-2015”, or “July 20, 2015”. Check out the docs for a full formatting guide.
Now let’s take a look at the test:
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestScript : MonoBehaviour { private const int NumIterations = 1000000; private string report; void Start() { var stopwatch = new System.Diagnostics.Stopwatch(); DateTime dt = DateTime.Now; stopwatch.Reset(); stopwatch.Start(); for (var i = 0; i < NumIterations; ++i) { dt = DateTime.Now; } var nowTime = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); for (var i = 0; i < NumIterations; ++i) { dt = dt.AddSeconds(123); } var addSecondsTime = stopwatch.ElapsedMilliseconds; var epochStart = new DateTime(1970, 1, 1); stopwatch.Reset(); stopwatch.Start(); for (var i = 0; i < NumIterations; ++i) { var timeSpan = dt - epochStart; } var subtractTime = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); for (var i = 0; i < NumIterations; ++i) { dt.ToString("dddd, MMMM d, yyyy"); } var toStringTime = stopwatch.ElapsedMilliseconds; report = "Operation,Time\n" + "DateTime.Now," + nowTime + "\n" + "DateTime.AddSeconds," + addSecondsTime + "\n" + "DateTime-DateTime," + subtractTime + "\n" + "DateTime.ToString," + toStringTime; } void OnGUI() { GUI.TextArea(new Rect(0, 0, Screen.width, Screen.height), report); } }
If you want to try out the test yourself, simply paste the above code into a TestScript.cs
file in your Unity project’s Assets
directory and attach it to the main camera game object in a new, empty project. Then build in non-development mode for 64-bit processors and run it windowed at 640×480 with fastest graphics. I ran it that way on this machine:
- 2.3 Ghz Intel Core i7-3615QM
- Mac OS X 10.10.4
- Unity 5.1.2f1, Mac OS X Standalone, x86_64, non-development
- 640×480, Fastest, Windowed
And here are the results I got:
Operation | Time |
---|---|
DateTime.Now | 86 |
DateTime.AddSeconds | 41 |
DateTime-DateTime | 13 |
DateTime.ToString | 1652 |
There are some pretty big speed differences between these functions, but they’re not really meant to be compared apples-to-apples. They’re unique operations, not alternatives for each other. What’s more important is their individual performance in an absolute sense.
To examine that, let’s consider that each operation was run one million times. This means that the slowest operation by far, ToString
took about 0.001652 milliseconds. That’s really not much time, even if it took much longer on a slower CPU. The other operations take one twentieth of that time, which is pretty much negligible.
The takeaway is that as long as you’re not performing thousands of DateTime
operations per frame, you’ll probably be just fine. It’s a pretty quick API, so go ahead and use it when you need absolute times.
Have you had any interesting come up when using DateTime
? Let me know in the comments!