Repository navigation
Get-Uptime is very slightly but increasingly inaccurate relative to Task Manager's up time #24432
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
Open Task Manager to the Performance tab and click on the CPU item on the left, and open a PowerShell command window simultaneously next to it. In the PowerShell window run Get-Uptime, note how the time doesn't match that given by Task Manager (listed at the bottom of the CPU page), it can be off by seconds to minutes or more depending on the uptime of the system. You can see in this StackOverflow answer how various methods of getting uptime have a drift relative to the "real" uptime as given by Task Manager (let's all assume Microsoft got it correct in Task Manager and it's the other methods that are wrong): https://stackoverflow.com/a/34010110/15743074, some methods have no drift while others do.
More info: The C# code behind Get-Uptime uses StopWatch.GetTimeStamp() which uses QueryPerformanceCounter, hidden behind a shim but the fact it uses QPC is also indicated on this Microsoft Learn page about high-resolution timestamps:
The primary API for native code is QueryPerformanceCounter (QPC). For managed code, the System.Diagnostics.Stopwatch class uses QPC as its precise time basis.
Which also states,
QPC is typically the best method to use to time-stamp events and measure small time intervals that occur on the same system or virtual machine.
And the page goes into examples of typical crystal oscillators used in computers and how they will drift relative to the real world by seconds per week. I suspect that when Windows synchronizes its time to a timeserver, any corrections to the time are applied to other time sources which is one of the ones Task Manager uses, so if the clock was fast by a second when it gets updated then some kernel counter has 1 second subtracted which causes Task Manager to show an accurate uptime, but the "number of ticks" does not get adjusted to remove a second--which is all the QPC timers use, an unsynchronized number of ticks.
High-resolution timestamps are accurate to microseconds, but microsecond accuracy doesn't hold over days and weeks, these high-resolution timestamps are intended for short profiling events. Get-Uptime is expected to return long times, sometimes even years if you have a server up forever, therefore it should not be using a high resolution timestamp under the hood because it has known issues with drift against real world clocks when used over days or longer.
Expected behavior
Task Manager "up time" and PowerShell `Get-Uptime` should match each other to a second or better.Actual behavior
Task Manager "up time" and PowerShell `Get-Uptime` are different from each other by seconds or more depending on the uptime of the system. My system has 13 day uptime and the difference is 8 seconds right now, which is admittedly very small at only 0.0007% off after 13 days. The accumulated error will be system dependent and represents an unsynchronized time.Error details
No response
Environment data
> $PSVersionTable
Name Value
---- -----
PSVersion 7.4.5
PSEdition Core
GitCommitId 7.4.5
OS Microsoft Windows 10.0.19044
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0Visuals
No response
Activity
similar-issues-ai commentedon Oct 14, 2024
We've found some similar issues:
If any of the above are duplicates, please consider closing this issue out and adding additional context in the original issue.
evelyn-bi commentedon Oct 14, 2024
I disagree that this is a duplicate:
This issue is about high performance counters being unsuitable (inaccurate) for timing long running things, such as the uptime of a system. The linked StackOverflow page gives some ideas for alternatives.
SteveL-MSFT commentedon Dec 4, 2024
The @PowerShell/wg-powershell-cmdlets discussed this. In our ad hoc testing, we also observed on some systems a drift as compared to using WMI. We would approve of a change to the cmdlet specific to Windows to use WMI to get the LastBootUpTime and subtracting from curren time as
(Get-Date).Subtract((get-ciminstance win32_operatingsystem).LastBootUpTime). The existing code would still be needed for Linux and macOS which doesn't have WMI.TobiasPSP commentedon Dec 4, 2024
I did a quick research on where WMI gets this information (as I assumed it might be just a registry key). However it turns out the boot time information is coming from some un(der)documented APIs. The well documented WMI route seems to be the best approach.
iSazonov commentedon Dec 25, 2024
I think it's worth leaving this cmdlet as it is until OS-s or .Net will not offer a standard API.Now there are several uptime sources (counters) with different behavior. Any of them may be suitable in some scenarios and unsuitable in others. https://stackoverflow.com/questions/972105/retrieve-system-uptime-using-c-sharp/34010110#34010110
For example, WMI requires elevated permissions for remote use.
In addition, there is no clear definition of uptime. What is the zero point? Are we talking about the start time or the time that has passed since the start of the system? Does this time include downtime or sleep time?
The best we can do is describe the drift problem in the documentation.
I found a deviation of GetUptime from WMI of several minutes on one system and no deviation on the other. I do not know what this is due to. But this is not important for support scenarios like "Has the user rebooted the system now?" or "Has the CU (requires a reboot) been installed on the system in the last month?"
iSazonov commentedon Jan 29, 2025
MacOS API to get boot time
https://github.com/usausa/prometheus-exporter-alternative/blob/70b8ebc7c9adf06d78777ffbec3d530eecd3cab2/PrometheusExporter.Instrumentation.SystemControl/SystemControlInstrumentation.cs#L68
https://github.com/usausa/prometheus-exporter-alternative/blob/main/PrometheusExporter.Instrumentation.SystemControl/NativeMethods.cs#L19
rhubarb-geek-nz commentedon Jan 30, 2025
I have put together a proof of concept module getting the boot time from Windows, Linux, MacOS and hopefully FreeBSD
For Windows it uses
For Linux it uses either
or
For MacOS and the *BSD it uses
Linux Docker images typically don't have uptime so if it is not present it gets the creation date of process 1.
iSazonov commentedon Jan 31, 2025
I'd prefer binary examples for supported OS-s.
rhubarb-geek-nz commentedon Jan 31, 2025
I also, but as a proof of concept it is about is it getting the information from the correct place and consistent.
rhubarb-geek-nz commentedon Feb 1, 2025
Rewritten in C# SinceYouAsk.cs using the example OSX DllImport
Running 7.4.5 on FreeBSD 13.3
iSazonov commentedon Feb 2, 2025
rhubarb-geek-nz Thanks! Some notices for your code.
/proc/uptimerhubarb-geek-nz commentedon Feb 2, 2025
True, it is very much work in progress at the moment! ReadLine does not work well at all. But the core SDK does give it an entry in OSPlatform, but not in netstandard2.0 Historically much of OSX/Darwin derives from FreeBSD.
Does it take into account hibernate/suspend times? If it counts clock tick interrupts then it will drift from true boot time.
I found that /proc/1 creation time was a reasonable proxy for boot time, except in the case of devices like Raspberry Pi with no real-time clock so they appear to boot at start of epoch until they read the time from disk or update from NTP.
iSazonov commentedon Feb 3, 2025
No.
From https://man7.org/linux/man-pages/man5/proc_uptime.5.html