New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Stopwatch.GetElapsedTime #65858
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsBackground and motivationStopwatch is a class and allocates, but when used for precision timing, you often don't want the overhead of that allocation, and it can be ergonomically inconvenient to try to cache an instance away somewhere. Developers that want to avoid that allocation end up using Stopwatch.GetTimestamp() directly, at which point they're having to remember what math to do and repeatedly do it for computing a TimeSpan from two timestamps. We can expose a helper to make that easier. API Proposalnamespace System.Diagnostics
{
public class Stopwatch
{
+ public static TimeSpan GetElapsedTime(long startingTimestamp) => GetElapsedTime(startTimestamp, Stopwatch.GetTimestamp());
+ public static TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp) => new TimeSpan((endTimestamp - startTimestamp) * s_tickFrequency);
}
} (based on the discussion in #48570 (comment)) API Usagelong starting = Stopwatch.GetTimestamp();
...
long ending = Stopwatch.GetTimestamp();
...
TimeSpan time = Stopwatch.GetElapsedTime(starting, ending); or long starting = Stopwatch.GetTimestamp();
...
TimeSpan time = Stopwatch.GetElapsedTime(starting); Alternative DesignsRisksNo response
|
public static TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp)
=> new TimeSpan((endTimestamp - startTimestamp) * s_tickFrequency); what happens when overflow? |
A new API for a one liner... I've seen a lot of APIs being rejected because of that. And they were for far more popular use cases than this. |
You can write very complicated code in "one line". The key aspect here is how hard is it to determine what the code should be and how hard is it to understand/read and determine its correctness. Note that the actual code someone external to Stopwatch would have to write is more like this: new TimeSpan((long)((Stopwatch.GetTimestamp() - startTimestamp) * (TimeSpan.TicksPerSecond / Stopwatch.Frequency))) I'm very experienced with .NET, but every time I need to come up with that "line" of code, I need to both consult the documentation and think hard about whether I've got it right. It is very non-obvious (in part because you need to understand the different units between the variable frequency of stopwatch and the 100-nanosecond tick unit of TimeSpan), which makes it a fine candidate for a new method. And it's more commonly needed than your comment suggests.
Which overflow? Do you mean if the value returned from GetTimestamp() fully wraps around the Int64 space? That's not new. This is the same logic employed by Stopwatch.Elapsed. |
Should we check if |
Ah. We could. For valid inputs it would take 29,000 years for it to actually overflow. But, sure, if we wanted to flag misuse, we could add a check that (ulong)end - (ulong)start was within bounds. My personal preference would be not to spend any additional cycles on such a check, but I don't feel strongly about it. |
My stance is the same. There is a preference for just doing the natural thing and that users would quickly realize the error point. This is more of a primitive building block and ideally something like Stopwatch itself could use these helpers without risking a regression. |
Tagging subscribers to this area: @tommcdon Issue DetailsBackground and motivationStopwatch is a class and allocates, but when used for precision timing, you often don't want the overhead of that allocation, and it can be ergonomically inconvenient to try to cache an instance away somewhere. Developers that want to avoid that allocation end up using Stopwatch.GetTimestamp() directly, at which point they're having to remember what math to do and repeatedly do it for computing a TimeSpan from two timestamps. We can expose a helper to make that easier. API Proposalnamespace System.Diagnostics
{
public class Stopwatch
{
+ public static TimeSpan GetElapsedTime(long startingTimestamp) => GetElapsedTime(startTimestamp, Stopwatch.GetTimestamp());
+ public static TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp) => new TimeSpan((long) ((endTimestamp - startTimestamp) * s_tickFrequency) );
}
} (based on the discussion in #48570 (comment)) API Usagelong starting = Stopwatch.GetTimestamp();
...
long ending = Stopwatch.GetTimestamp();
...
TimeSpan time = Stopwatch.GetElapsedTime(starting, ending); or long starting = Stopwatch.GetTimestamp();
...
TimeSpan time = Stopwatch.GetElapsedTime(starting); Alternative DesignsRisksNo response
|
Notably, I think this is also |
An alternative would be the proposed This would free the user from thinking about timestamps and frequencies. A
|
Such a type would still need this calculation, so I don't see it as an alternative; if such a thing were to be added, it would be built on top of this building block. Fundamentally Stopwatch today exposes a method to get a timestamp but then nothing to use it / translate it into a meaningful value... this fills that gap. |
There is a comment within Stopwatch.Stop() that appears to be relevant. Maybe a check for negative is necessary.
|
Negative is ok, I think. |
namespace System.Diagnostics
{
public partial class Stopwatch
{
public static TimeSpan GetElapsedTime(long startingTimestamp);
public static TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp);
}
} |
Background and motivation
Stopwatch is a class and allocates, but when used for precision timing, you often don't want the overhead of that allocation, and it can be ergonomically inconvenient to try to cache an instance away somewhere. Developers that want to avoid that allocation end up using Stopwatch.GetTimestamp() directly, at which point they're having to remember what math to do and repeatedly do it for computing a TimeSpan from two timestamps. We can expose a helper to make that easier.
API Proposal
(based on the discussion in #48570 (comment))
API Usage
or
Alternative Designs
#48570
Risks
No response
The text was updated successfully, but these errors were encountered: