diff options
author | Toni Uhlig <Toni.Uhlig@tq-group.com> | 2017-12-05 16:07:23 +0100 |
---|---|---|
committer | Toni Uhlig <Toni.Uhlig@tq-group.com> | 2017-12-05 16:28:14 +0100 |
commit | 3c79f311cfd32f7f4508b6225a90d9caf567e923 (patch) | |
tree | e804539678bfbfa0664aa44e5bdc9309db5e94be | |
parent | aca4821babd7b6eed20b114a9f6c26e8f978198f (diff) |
print job timings (average, total, estimated remaining time), removed developer info
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | src/JobQueue.cpp | 22 | ||||
-rw-r--r-- | src/JobQueue.hpp | 8 | ||||
-rw-r--r-- | src/UpdateGUI.cpp | 66 |
4 files changed, 79 insertions, 19 deletions
@@ -1,3 +1 @@ Toni Uhlig -Valeri Budjko -Theres Teichmann diff --git a/src/JobQueue.cpp b/src/JobQueue.cpp index 8395353..4f85619 100644 --- a/src/JobQueue.cpp +++ b/src/JobQueue.cpp @@ -28,6 +28,15 @@ void Queue::Report(const Job::JobEvents& cmd, const wxString& sArg, int iArg) m_pParent->AddPendingEvent(evt); } +void Queue::ReportDone(const JobReport& jobReport, const wxString& sArg, int iArg) +{ + wxCommandEvent evt(wxEVT_THREAD, Job::eID_THREAD_JOB_DONE); + evt.SetString(sArg); + evt.SetInt(iArg); + evt.SetClientObject(new JobReport(jobReport)); + m_pParent->AddPendingEvent(evt); +} + wxThread::ExitCode WorkerThread::doWork() { Sleep(1000); @@ -41,11 +50,14 @@ wxThread::ExitCode WorkerThread::doWork() void WorkerThread::doJob() { int rv; + std::time_t jobStart, jobEnd; + unsigned diffTime; std::string err; UpdateFactory uf; Job job = m_pQueue->Pop(); m_pQueue->incBusyWorker(); + jobStart = std::time(nullptr); /* process the job which was started by the GUI */ switch(job.cmdEvent) @@ -128,8 +140,12 @@ void WorkerThread::doJob() default: break; } - m_pQueue->Report(Job::eID_THREAD_JOB_DONE, - wxString::Format(wxT("Job #%d: finished."), - job.cmdArgs.jobid), m_ID); + + jobEnd = std::time(nullptr); + diffTime = std::difftime(jobEnd, jobStart); + + m_pQueue->ReportDone(JobReport(diffTime), + wxString::Format(wxT("Job #%d: finished. Time consumed: %umin %usec"), + job.cmdArgs.jobid, (diffTime / 60), (diffTime % 60)), m_ID); m_pQueue->decBusyWorker(); } diff --git a/src/JobQueue.hpp b/src/JobQueue.hpp index 519903d..ddf2f33 100644 --- a/src/JobQueue.hpp +++ b/src/JobQueue.hpp @@ -39,6 +39,13 @@ struct JobArgs std::string password; }; +struct JobReport : public wxClientData +{ + JobReport(double jTime) + : jobTime(jTime) {} + double jobTime; +}; + struct Job { enum JobEvents @@ -76,6 +83,7 @@ public: Job Pop(); /* report back to parent */ void Report(const Job::JobEvents& cmd, const wxString& sArg = wxEmptyString, int iArg = 0); + void ReportDone(const JobReport& jobReport, const wxString& sArg = wxEmptyString, int iArg = 0); size_t Stacksize() { wxMutexLocker lock(m_MutexQueue); diff --git a/src/UpdateGUI.cpp b/src/UpdateGUI.cpp index 5620020..a411ad5 100644 --- a/src/UpdateGUI.cpp +++ b/src/UpdateGUI.cpp @@ -6,6 +6,7 @@ #include <iostream> #include <iomanip> +#include <tuple> #include <chrono> #include <ctime> #include <wx/aboutdlg.h> @@ -210,8 +211,6 @@ void UpdateGUIFrame::OnAbout(wxCommandEvent& event) aboutInfo.SetCopyright("(C) 2017"); aboutInfo.SetWebSite(PACKAGE_URL); aboutInfo.AddDeveloper("Toni Uhlig"); - aboutInfo.AddDeveloper("Valeri Budjko"); - aboutInfo.AddDeveloper("Theres Teichmann"); aboutInfo.SetLicense(wxString( "TQ-Systems Software License Agreement Version 1.0.1\n\n" "wxWidgets: wxWindows Library Licence, Version 3.1\n" @@ -228,6 +227,7 @@ void UpdateGUIFrame::OnAbout(wxCommandEvent& event) void UpdateGUIFrame::OnEditor(wxCommandEvent& event) { + /* StatusLog Events: not used atm */ } void UpdateGUIFrame::OnUpdateFile(wxCommandEvent& event) @@ -266,10 +266,12 @@ void UpdateGUIFrame::OnImportCSV(wxCommandEvent& event) tLog(RTL_DEFAULT, wxString::Format(wxT("CSV File: \"%s\""), openFileDialog.GetPath())); loadUpdateFactoriesFromCSV(openFileDialog.GetPath(), imgEntry->GetValue(), uf, error_list); + /* check for CSV read errors */ for (auto& errstr : error_list) { tLog(RTL_RED, wxString::Format(wxT("CSV read error: \"%s\""), errstr)); } + /* add all csv jobs to the job queue */ jobid = rand(); for (auto *u : uf) { jobs->AddJob(Job(Job::eID_THREAD_JOB, JobArgs(jobid, *u))); @@ -300,6 +302,7 @@ void UpdateGUIFrame::OnUpdate(wxCommandEvent& event) str = ipEntry->GetValue(); /* parse multiple hostname:port combinations */ loadUpdateFactoriesFromStr(str, imgEntry->GetValue(), pwEntry->GetValue(), uf); + /* add all jobs to the job queue */ int jobid = rand(); for (auto *u : uf) { std::ostringstream log; @@ -307,8 +310,7 @@ void UpdateGUIFrame::OnUpdate(wxCommandEvent& event) tLog(RTL_DEFAULT, log.str().c_str()); jobs->AddJob(Job(Job::eID_THREAD_JOB, JobArgs(jobid, *u))); - delete u; - + delete u; /* do not leak heap memory */ jobid++; } } @@ -323,12 +325,38 @@ void UpdateGUIFrame::OnNavigationKey(wxNavigationKeyEvent& event) } } +/* return a tuple(avgJobTime[sec], totJobTime[min], estJobTime[min]) */ +static std::tuple<unsigned, unsigned, unsigned> +calcJobTimingsAvgTotEst(Queue& jobs, size_t parallelJobCount, JobReport& jobReport, std::vector<unsigned>& jobTimings) +{ + unsigned avg = 0, tot = 0, est; + unsigned jobTime = jobReport.jobTime; + + jobTimings.push_back(jobTime); + /* calculate an average/total */ + for (auto& time : jobTimings) { + avg += time; + tot += time; + } + avg /= jobTimings.size(); + /* Not the best solution since we dont know exactly + * how much jobs are running in parallel. + */ + tot = (tot / parallelJobCount) / 60; + est = (avg * (jobs.Stacksize() + jobs.getBusyWorker())) / 60; + + return std::make_tuple(avg, tot, est); +} + void UpdateGUIFrame::OnThread(wxCommandEvent& event) { wxString wxs; LogType tp = RTL_DEFAULT; static size_t counter = 0; - bool printAllJobsDone = false; + static std::vector<unsigned> jobTimings; + unsigned avgJobTime = 0, totJobTime = 0, estTotalJobTime = 0; + bool allJobsDone = false; + JobReport *jobReport = nullptr; /* some periodic informational output */ if ((++counter % 30) == 0) { @@ -347,17 +375,20 @@ void UpdateGUIFrame::OnThread(wxCommandEvent& event) switch (event.GetId()) { case Job::eID_THREAD_JOB_DONE: + /* calculate job execution times (total/average/estimated) */ + jobReport = dynamic_cast<JobReport *>(event.GetClientObject()); + std::tie (avgJobTime, totJobTime, estTotalJobTime) = calcJobTimingsAvgTotEst(*jobs, threads.size(), *jobReport, jobTimings); /* If more then one job was in the queue - * inform the user about job completion. + * inform the user about job completion, + * otherwise reset completed job counter. */ if (jobs->Stacksize() == 0 && jobs->getBusyWorker() == 0) { - if (jobs->getTotalJobsDone() > 1) { - counter = 0; - printAllJobsDone = true; - } + if (jobs->getTotalJobsDone() > 1) + allJobsDone = true; jobs->resetTotalJobsDone(); } else { - SetStatusText(wxs + wxString::Format(wxT(" (jobs remaining: %u)"), jobs->Stacksize() + jobs->getBusyWorker())); + SetStatusText(wxString::Format(wxT("Jobs remaining: %u, estimated remaining time: %umin"), + jobs->Stacksize() + jobs->getBusyWorker(), estTotalJobTime)); } break; case Job::eID_THREAD_JOB: SetStatusText(wxs); break; @@ -367,18 +398,25 @@ void UpdateGUIFrame::OnThread(wxCommandEvent& event) tLog(tp, wxs); break; case Job::eID_THREAD_EXIT: + /* should only be run once per thread and only if the app exits */ SetStatusText(wxString::Format(wxT("Thread [%i]: Stopped."), event.GetInt())); threads.remove(event.GetInt()); if (threads.empty()) { this->OnExit(event); } break; case Job::eID_THREAD_STARTED: + /* should only be run once per thread and only if the app starts */ SetStatusText(wxString::Format(wxT("Thread [%i]: Ready."), event.GetInt())); break; default: event.Skip(); } - if (printAllJobsDone) { - SetStatusText(wxT("All jobs finished.")); - tLog(RTL_GREEN, "All jobs finished."); + /* job queue is now empty and had more than one job */ + if (allJobsDone) { + counter = 0; + /* we presume that threads.size() jobs ran at the same time */ + wxs = wxString::Format(wxT("All jobs finished. Time consumption: %umin (average per device: %umin %usec)"), (unsigned)((float)totJobTime + 0.5f) /* roundup */, avgJobTime / 60, avgJobTime % 60); + SetStatusText(wxs); + tLog(RTL_GREEN, wxs); + jobTimings.clear(); } } |