smooth out remaining-time prediction

This commit is contained in:
David Rose 2010-02-04 02:03:06 +00:00
parent e775c9f307
commit aae5068ad3
2 changed files with 62 additions and 12 deletions

View File

@ -59,6 +59,10 @@ typedef P3DX11SplashWindow SplashWindowType;
typedef P3DSplashWindow SplashWindowType;
#endif
// The amount of time (in seconds) over which we average the total
// download time, for smoothing out the time estimate.
static const double time_average = 10.0;
// These are the various image files we might download for use in the
// splash window. This list must match the ImageType enum.
const char *P3DInstance::_image_type_names[P3DInstance::IT_num_image_types] = {
@ -102,6 +106,7 @@ P3DInstance(P3D_request_ready_func *func,
_panda_script_object->set_instance(this);
_user_data = user_data;
_request_pending = false;
_total_time_reports = 0;
_temp_p3d_filename = NULL;
_image_package = NULL;
_current_background_image = IT_none;
@ -410,7 +415,7 @@ set_p3d_url(const string &p3d_url) {
make_splash_window();
// Mark the time we started downloading, so we'll know when to reveal
// the progress bar.
// the progress bar, and we can predict the total download time.
#ifdef _WIN32
_start_dl_instance_tick = GetTickCount();
#else
@ -2752,7 +2757,6 @@ ready_to_install() {
_download_complete = false;
_download_package_index = 0;
_total_downloaded = 0;
_download_begin = time(NULL);
nout << "Beginning install of " << _downloading_packages.size()
<< " packages, total " << _total_download_size
@ -2977,19 +2981,55 @@ report_package_progress(P3DPackage *package, double progress) {
static const size_t buffer_size = 256;
char buffer[buffer_size];
time_t elapsed = time(NULL) - _download_begin;
_panda_script_object->set_int_property("downloadElapsedSeconds", (int)elapsed);
// Get the floating-point elapsed time.
#ifdef _WIN32
int now = GetTickCount();
double elapsed = (double)(now - _start_dl_instance_tick) * 0.001;
#else
struct timeval now;
gettimeofday(&now, NULL);
double elapsed = (double)(now.tv_sec - _start_dl_instance_timeval.tv_sec) +
(double)(now.tv_usec - _start_dl_instance_timeval.tv_usec) / 1000000.0;
#endif
sprintf(buffer, "%d:%02d", (int)(elapsed / 60), (int)(elapsed % 60));
int ielapsed = (int)elapsed;
_panda_script_object->set_int_property("downloadElapsedSeconds", ielapsed);
sprintf(buffer, "%d:%02d", ielapsed / 60, ielapsed % 60);
_panda_script_object->set_string_property("downloadElapsedFormatted", buffer);
if (progress > 0 && (elapsed > 5 || progress > 0.2)) {
time_t total = (time_t)((double)elapsed / progress);
time_t remaining = max(total, elapsed) - elapsed;
_panda_script_object->set_int_property("downloadRemainingSeconds", (int)remaining);
sprintf(buffer, "%d:%02d", (int)(remaining / 60), (int)(remaining % 60));
if (progress > 0 && (elapsed > 5.0 || progress > 0.2)) {
double this_total = elapsed / progress;
double this_remaining = max(this_total - elapsed, 0.0);
// Age out any old time reports.
double old = elapsed - min(time_average, this_remaining);
while (!_time_reports.empty() && _time_reports.front()._report_time < old) {
TimeReport &tr0 = _time_reports.front();
_total_time_reports -= tr0._total;
_time_reports.pop_front();
}
if (_time_reports.empty()) {
_total_time_reports = 0.0;
}
// Add a new time report.
TimeReport tr;
tr._total = this_total;
tr._report_time = elapsed;
_time_reports.push_back(tr);
_total_time_reports += tr._total;
// Now get the average report.
if (!_time_reports.empty()) {
double total = _total_time_reports / (double)_time_reports.size();
double remaining = max(total - elapsed, 0.0);
int iremaining = (int)(remaining + 0.5);
_panda_script_object->set_int_property("downloadRemainingSeconds", iremaining);
sprintf(buffer, "%d:%02d", iremaining / 60, iremaining % 60);
_panda_script_object->set_string_property("downloadRemainingFormatted", buffer);
}
}
}
////////////////////////////////////////////////////////////////////

View File

@ -234,6 +234,17 @@ private:
string _origin_hostname;
string _origin_port;
// We need a list of previous time reports so we can average the
// predicted download time over the past few seconds.
class TimeReport {
public:
double _total;
double _report_time;
};
typedef deque<TimeReport> TimeReports;
TimeReports _time_reports;
double _total_time_reports;
P3DTemporaryFile *_temp_p3d_filename;
// For downloading the various images used by the splash window.
@ -333,7 +344,6 @@ private:
int _download_package_index;
size_t _total_download_size;
size_t _total_downloaded;
time_t _download_begin;
bool _download_started;
bool _download_complete;
bool _instance_started;