Browse Source

Use a steady clock source for progress reporting

Clock changes while apt is running can result in strange reports
confusing (and amusing) users. Sadly, to keep the ABI for now the
code is a bit more ugly than it would need to be.
tags/debian/1.7.0_alpha1
David Kalnischkies 3 years ago
parent
commit
79b61ae767
3 changed files with 85 additions and 64 deletions
  1. +35
    -27
      apt-pkg/acquire.cc
  2. +12
    -5
      apt-pkg/contrib/progress.cc
  3. +38
    -32
      ftparchive/apt-ftparchive.cc

+ 35
- 27
apt-pkg/acquire.cc View File

@@ -23,6 +23,7 @@
#include <apt-pkg/strutl.h>

#include <algorithm>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <memory>
@@ -1256,6 +1257,13 @@ pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(-1), Update(true), MoreP
/* This computes some internal state variables for the derived classes to
use. It generates the current downloaded bytes and total bytes to download
as well as the current CPS estimate. */
static struct timeval GetTimevalFromSteadyClock()
{
auto const Time = std::chrono::steady_clock::now().time_since_epoch();
auto const Time_sec = std::chrono::duration_cast<std::chrono::seconds>(Time);
auto const Time_usec = std::chrono::duration_cast<std::chrono::microseconds>(Time - Time_sec);
return { Time_sec.count(), Time_usec.count() };
}
bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
{
TotalBytes = 0;
@@ -1314,21 +1322,22 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
CurrentBytes = TotalBytes;

// Compute the CPS
struct timeval NewTime;
gettimeofday(&NewTime,0);
struct timeval NewTime = GetTimevalFromSteadyClock();
if ((NewTime.tv_sec - Time.tv_sec == 6 && NewTime.tv_usec > Time.tv_usec) ||
NewTime.tv_sec - Time.tv_sec > 6)
{
double Delta = NewTime.tv_sec - Time.tv_sec +
(NewTime.tv_usec - Time.tv_usec)/1000000.0;
{
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - Time.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - Time.tv_usec);

// Compute the CPS value
if (Delta < 0.01)
if (Delta < std::chrono::milliseconds(10))
CurrentCPS = 0;
else
CurrentCPS = ((CurrentBytes - ResumeSize) - LastBytes)/Delta;
CurrentCPS = ((CurrentBytes - ResumeSize) - LastBytes)/ Delta.count();
LastBytes = CurrentBytes - ResumeSize;
ElapsedTime = std::llround(Delta);
ElapsedTime = llround(Delta.count());
Time = NewTime;
}

@@ -1360,21 +1369,21 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
return true;

int fd = _config->FindI("APT::Status-Fd",-1);
if(fd > 0)
if(fd > 0)
{
ostringstream status;

char msg[200];
long i = CurrentItems < TotalItems ? CurrentItems + 1 : CurrentItems;
unsigned long long ETA = 0;
if(CurrentCPS > 0)
if(CurrentCPS > 0 && TotalBytes > CurrentBytes)
ETA = (TotalBytes - CurrentBytes) / CurrentCPS;

std::string msg;
long i = CurrentItems < TotalItems ? CurrentItems + 1 : CurrentItems;
// only show the ETA if it makes sense
if (ETA > 0 && ETA < 172800 /* two days */ )
snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
if (ETA > 0 && ETA < std::chrono::seconds(std::chrono::hours(24 * 2)).count())
strprintf(msg, _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
else
snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
strprintf(msg, _("Retrieving file %li of %li"), i, TotalItems);

// build the status str
std::ostringstream str;
@@ -1393,8 +1402,7 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
/* We just reset the counters */
void pkgAcquireStatus::Start()
{
gettimeofday(&Time,0);
gettimeofday(&StartTime,0);
Time = StartTime = GetTimevalFromSteadyClock();
LastBytes = 0;
CurrentCPS = 0;
CurrentBytes = 0;
@@ -1411,19 +1419,19 @@ void pkgAcquireStatus::Start()
void pkgAcquireStatus::Stop()
{
// Compute the CPS and elapsed time
struct timeval NewTime;
gettimeofday(&NewTime,0);
double Delta = NewTime.tv_sec - StartTime.tv_sec +
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
struct timeval NewTime = GetTimevalFromSteadyClock();
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - StartTime.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - StartTime.tv_usec);
// Compute the CPS value
if (Delta < 0.01)
if (Delta < std::chrono::milliseconds(10))
CurrentCPS = 0;
else
CurrentCPS = FetchedBytes/Delta;
CurrentCPS = FetchedBytes / Delta.count();
LastBytes = CurrentBytes;
ElapsedTime = std::llround(Delta);
ElapsedTime = llround(Delta.count());
}
/*}}}*/
// AcquireStatus::Fetched - Called when a byte set has been fetched /*{{{*/


+ 12
- 5
apt-pkg/contrib/progress.cc View File

@@ -14,6 +14,7 @@
#include <apt-pkg/progress.h>

#include <cmath>
#include <chrono>
#include <cstring>
#include <iostream>
#include <string>
@@ -115,12 +116,18 @@ bool OpProgress::CheckChange(float Interval)
return false;
// Check time delta
struct timeval Now;
gettimeofday(&Now,0);
decltype(Interval) const Diff = Now.tv_sec - LastTime.tv_sec + (Now.tv_usec - LastTime.tv_usec)/1000000.0;
if (Diff < Interval)
auto const Now = std::chrono::steady_clock::now().time_since_epoch();
auto const Now_sec = std::chrono::duration_cast<std::chrono::seconds>(Now);
auto const Now_usec = std::chrono::duration_cast<std::chrono::microseconds>(Now - Now_sec);
struct timeval NowTime = { Now_sec.count(), Now_usec.count() };

std::chrono::duration<decltype(Interval)> Delta =
std::chrono::seconds(NowTime.tv_sec - LastTime.tv_sec) +
std::chrono::microseconds(NowTime.tv_sec - LastTime.tv_usec);

if (Delta.count() < Interval)
return false;
LastTime = Now;
LastTime = NowTime;
return true;
}
/*}}}*/


+ 38
- 32
ftparchive/apt-ftparchive.cc View File

@@ -23,6 +23,7 @@
#include <apt-private/private-output.h>

#include <algorithm>
#include <chrono>
#include <climits>
#include <functional>
#include <iostream>
@@ -33,6 +34,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>

#include "apt-ftparchive.h"
#include "cachedb.h"
@@ -46,6 +48,15 @@
using namespace std;
unsigned Quiet = 0;

static struct timeval GetTimevalFromSteadyClock() /*{{{*/
{
auto const Time = std::chrono::steady_clock::now().time_since_epoch();
auto const Time_sec = std::chrono::duration_cast<std::chrono::seconds>(Time);
auto const Time_usec = std::chrono::duration_cast<std::chrono::microseconds>(Time - Time_sec);
return { Time_sec.count(), Time_usec.count() };
}
/*}}}*/

// struct PackageMap - List of all package files in the config file /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -173,9 +184,8 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
string OverrideDir = Setup.FindDir("Dir::OverrideDir");
string CacheDir = Setup.FindDir("Dir::CacheDir");

struct timeval StartTime;
gettimeofday(&StartTime,0);
struct timeval StartTime = GetTimevalFromSteadyClock();

PkgDone = true;
// Create a package writer object.
@@ -232,15 +242,15 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
else
c0out << ' ';
struct timeval NewTime;
gettimeofday(&NewTime,0);
double Delta = NewTime.tv_sec - StartTime.tv_sec +
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
struct timeval NewTime = GetTimevalFromSteadyClock();
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - StartTime.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - StartTime.tv_usec);

c0out << Packages.Stats.Packages << " files " <<
/* SizeToStr(Packages.Stats.MD5Bytes) << "B/" << */
SizeToStr(Packages.Stats.Bytes) << "B " <<
TimeToStr((long)Delta) << endl;
TimeToStr(llround(Delta.count())) << endl;

if(_config->FindB("APT::FTPArchive::ShowCacheMisses", false) == true)
c0out << " Misses in Cache: " << Packages.Stats.Misses<< endl;
@@ -264,9 +274,7 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
string OverrideDir = Setup.FindDir("Dir::OverrideDir");
string CacheDir = Setup.FindDir("Dir::CacheDir");

struct timeval StartTime;
gettimeofday(&StartTime,0);
struct timeval StartTime = GetTimevalFromSteadyClock();
SrcDone = true;
// Create a package writer object.
@@ -320,13 +328,13 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
else
c0out << ' ';
struct timeval NewTime;
gettimeofday(&NewTime,0);
double Delta = NewTime.tv_sec - StartTime.tv_sec +
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
struct timeval NewTime = GetTimevalFromSteadyClock();
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - StartTime.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - StartTime.tv_usec);
c0out << Sources.Stats.Packages << " pkgs in " <<
TimeToStr((long)Delta) << endl;
TimeToStr(llround(Delta.count())) << endl;

if(_config->FindB("APT::FTPArchive::ShowCacheMisses", false) == true)
c0out << " Misses in Cache: " << Sources.Stats.Misses << endl;
@@ -356,10 +364,9 @@ bool PackageMap::GenContents(Configuration &Setup,
string ArchiveDir = Setup.FindDir("Dir::ArchiveDir");
string CacheDir = Setup.FindDir("Dir::CacheDir");
string OverrideDir = Setup.FindDir("Dir::OverrideDir");
struct timeval StartTime;
gettimeofday(&StartTime,0);

struct timeval StartTime = GetTimevalFromSteadyClock();

// Create a package writer object.
MultiCompress Comp(flCombine(ArchiveDir,this->Contents),
CntCompress,Permissions);
@@ -437,17 +444,17 @@ bool PackageMap::GenContents(Configuration &Setup,
else
c0out << ' ';
struct timeval NewTime;
gettimeofday(&NewTime,0);
double Delta = NewTime.tv_sec - StartTime.tv_sec +
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
struct timeval NewTime = GetTimevalFromSteadyClock();
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - StartTime.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - StartTime.tv_usec);
if(_config->FindB("APT::FTPArchive::ShowCacheMisses", false) == true)
c0out << " Misses in Cache: " << Contents.Stats.Misses<< endl;

c0out << Contents.Stats.Packages << " files " <<
SizeToStr(Contents.Stats.Bytes) << "B " <<
TimeToStr((long)Delta) << endl;
TimeToStr(llround(Delta.count())) << endl;
return true;
}
@@ -926,8 +933,7 @@ static bool Generate(CommandLine &CmdL)
if (CmdL.FileSize() < 2)
return ShowHelp(CmdL);

struct timeval StartTime;
gettimeofday(&StartTime,0);
struct timeval StartTime = GetTimevalFromSteadyClock();
struct CacheDB::Stats Stats;
// Read the configuration file.
@@ -964,12 +970,12 @@ static bool Generate(CommandLine &CmdL)
return false;
}

struct timeval NewTime;
gettimeofday(&NewTime,0);
double Delta = NewTime.tv_sec - StartTime.tv_sec +
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
struct timeval NewTime = GetTimevalFromSteadyClock();
std::chrono::duration<double> Delta =
std::chrono::seconds(NewTime.tv_sec - StartTime.tv_sec) +
std::chrono::microseconds(NewTime.tv_sec - StartTime.tv_usec);
c1out << "Done. " << SizeToStr(Stats.Bytes) << "B in " << Stats.Packages
<< " archives. Took " << TimeToStr((long)Delta) << endl;
<< " archives. Took " << TimeToStr(llround(Delta.count())) << endl;

UnloadTree(TransList);
return true;


Loading…
Cancel
Save