Browse Source

[util] Better precision of the ProcessUptime on linux

The  ProcessUptime function should now usually return a value less than 20 ms if called at the start of the program.
0961a518fdaee4fd243b01c7cf5433dd768897c4
swarmer 9 months ago
parent
commit
f461772a29
1 changed files with 9 additions and 3 deletions
  1. 9 3
      util/datetime/process_uptime.cpp

+ 9 - 3
util/datetime/process_uptime.cpp

@@ -32,14 +32,20 @@ TDuration ProcessUptime() {
     TUnbufferedFileInput statFile(statPath);
     auto statStr = statFile.ReadAll();
     const auto completeStatsSize = 20; // First two fields skipped to ignore variations of parentheses
-    TVector<TString> stats = StringSplitter(TStringBuf{statStr}.RAfter(')').After(' ')).Split(' ').Take(completeStatsSize);
+    const TVector<TStringBuf> stats = StringSplitter(TStringBuf{statStr}.RAfter(')').After(' ')).Split(' ').Take(completeStatsSize);
     ui64 startTimeTicks = 0;
     Y_THROW_UNLESS(stats.size() == completeStatsSize, "Broken format of " << statPath);
     if (!TryFromString<ui64>(stats.back(), startTimeTicks)) {
         ythrow yexception() << "Failed to extract process starttime value from " << statPath;
     }
-    auto startTimeSeconds = startTimeTicks / sysconf(_SC_CLK_TCK);
-    return Uptime() - TDuration::Seconds(startTimeSeconds);
+    long ticksPerSecond = sysconf(_SC_CLK_TCK);
+    Y_THROW_UNLESS_EX(ticksPerSecond != -1, TSystemError() << "Failed to get _SC_CLK_TCK");
+    Y_THROW_UNLESS(ticksPerSecond > 0, "Invalid value of the _SC_CLK_TCK variable: " << ticksPerSecond);
+    const ui64 startTimeSeconds = startTimeTicks / ticksPerSecond;
+    const ui64 fractionTicks = startTimeTicks % ticksPerSecond;
+    const TDuration startTimeFractionSeconds = TDuration::MicroSeconds(1'000'000u * fractionTicks / ticksPerSecond);
+    const TDuration startTime = TDuration::Seconds(startTimeSeconds) + startTimeFractionSeconds;
+    return Uptime() - startTime;
 #else
     ythrow yexception() << "unimplemented";
 #endif