From 79b61ae7673eb6213493e2cb202f0d70c390932d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 May 2018 17:36:08 +0200 Subject: 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. --- apt-pkg/acquire.cc | 62 ++++++++++++++++++++++----------------- apt-pkg/contrib/progress.cc | 17 +++++++---- ftparchive/apt-ftparchive.cc | 70 ++++++++++++++++++++++++-------------------- 3 files changed, 85 insertions(+), 64 deletions(-) diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 1e037231d..0fee80c5d 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -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(Time); + auto const Time_usec = std::chrono::duration_cast(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 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 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 /*{{{*/ diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc index 3bccc48d4..806bd47f8 100644 --- a/apt-pkg/contrib/progress.cc +++ b/apt-pkg/contrib/progress.cc @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -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(Now); + auto const Now_usec = std::chrono::duration_cast(Now - Now_sec); + struct timeval NowTime = { Now_sec.count(), Now_usec.count() }; + + std::chrono::duration 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; } /*}}}*/ diff --git a/ftparchive/apt-ftparchive.cc b/ftparchive/apt-ftparchive.cc index a3fdf2391..077701cc0 100644 --- a/ftparchive/apt-ftparchive.cc +++ b/ftparchive/apt-ftparchive.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #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(Time); + auto const Time_usec = std::chrono::duration_cast(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 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 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 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 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; -- cgit v1.2.3 From 2fc09a90e7e62a4c3e4a67506bf90fcf4c6ccfaf Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 May 2018 21:28:55 +0200 Subject: Remove unused time-tracking from http method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Stats method isn't called anywhere, was partly commented out before, but we keep updating the time for it – lets avoid this pointless busywork. Gbp-Dch: Ignore --- methods/http.cc | 17 ----------------- methods/http.h | 3 --- 2 files changed, 20 deletions(-) diff --git a/methods/http.cc b/methods/http.cc index 3862497a8..1933d9d00 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -134,8 +134,6 @@ bool CircleBuf::Read(std::unique_ptr const &Fd) return false; } - if (InP == 0) - gettimeofday(&Start,0); InP += Res; } } @@ -267,21 +265,6 @@ bool CircleBuf::Write(string &Data) return true; } /*}}}*/ -// CircleBuf::Stats - Print out stats information /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CircleBuf::Stats() -{ - if (InP == 0) - return; - - struct timeval Stop; - gettimeofday(&Stop,0); -/* float Diff = Stop.tv_sec - Start.tv_sec + - (float)(Stop.tv_usec - Start.tv_usec)/1000000; - clog << "Got " << InP << " in " << Diff << " at " << InP/Diff << endl;*/ -} - /*}}}*/ CircleBuf::~CircleBuf() /*{{{*/ { delete [] Buf; diff --git a/methods/http.h b/methods/http.h index d511196e3..ae6cedc13 100644 --- a/methods/http.h +++ b/methods/http.h @@ -36,7 +36,6 @@ class CircleBuf std::string OutQueue; unsigned long long StrPos; unsigned long long MaxGet; - struct timeval Start; static unsigned long long BwReadLimit; static unsigned long long BwTickReadData; @@ -85,8 +84,6 @@ class CircleBuf bool WriteSpace() const {return InP - OutP > 0;}; void Reset(); - // Dump everything - void Stats(); CircleBuf(HttpMethod const * const Owner, unsigned long long Size); ~CircleBuf(); -- cgit v1.2.3 From f6655a1138a11e80884959014939a25f23a1e308 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 May 2018 21:26:03 +0200 Subject: Use steady clock source for bandwidth limitation Using the time of day for this is slightly wrong just like it is for progress, just less visible. --- methods/http.cc | 18 +++++++++--------- methods/http.h | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/methods/http.cc b/methods/http.cc index 1933d9d00..2e7fca307 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,7 @@ using namespace std; unsigned long long CircleBuf::BwReadLimit=0; unsigned long long CircleBuf::BwTickReadData=0; -struct timeval CircleBuf::BwReadTick={0,0}; +std::chrono::steady_clock::duration CircleBuf::BwReadTick{0}; const unsigned int CircleBuf::BW_HZ=10; // CircleBuf::CircleBuf - Circular input buffer /*{{{*/ @@ -98,18 +99,17 @@ bool CircleBuf::Read(std::unique_ptr const &Fd) unsigned long long const BwReadMax = CircleBuf::BwReadLimit/BW_HZ; if(CircleBuf::BwReadLimit) { - struct timeval now; - gettimeofday(&now,0); + auto const now = std::chrono::steady_clock::now().time_since_epoch(); + auto const d = now - CircleBuf::BwReadTick; - unsigned long long d = (now.tv_sec-CircleBuf::BwReadTick.tv_sec)*1000000 + - now.tv_usec-CircleBuf::BwReadTick.tv_usec; - if(d > 1000000/BW_HZ) { + auto const tickLen = std::chrono::microseconds(std::chrono::seconds(1)) / BW_HZ; + if(d > tickLen) { CircleBuf::BwReadTick = now; CircleBuf::BwTickReadData = 0; - } - + } + if(CircleBuf::BwTickReadData >= BwReadMax) { - usleep(1000000/BW_HZ); + usleep(tickLen.count()); return true; } } diff --git a/methods/http.h b/methods/http.h index ae6cedc13..5668f0b87 100644 --- a/methods/http.h +++ b/methods/http.h @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -39,7 +40,7 @@ class CircleBuf static unsigned long long BwReadLimit; static unsigned long long BwTickReadData; - static struct timeval BwReadTick; + static std::chrono::steady_clock::duration BwReadTick; static const unsigned int BW_HZ; unsigned long long LeftRead() const -- cgit v1.2.3