diff --git a/include/library/workthread.hpp b/include/library/workthread.hpp index bcce5b47..736bf3e0 100644 --- a/include/library/workthread.hpp +++ b/include/library/workthread.hpp @@ -85,6 +85,14 @@ public: * Note: Don't call from outside workthread code. */ int operator()(int dummy); +/** + * Get wait counters. + * + * Retrns: Two-element tuple. + * - The first element is the amount of microseconds wait_busy() has waited. + * - The second element is the amount of microseconds wait_workflag() has waited. + */ + std::pair get_wait_count(); protected: /** * Thread entrypoint. @@ -106,6 +114,8 @@ private: volatile bool busy; volatile bool exception_caught; volatile bool exception_oom; + volatile uint64_t waitamt_busy; + volatile uint64_t waitamt_work; std::string exception_text; }; diff --git a/include/video/avi/codec.hpp b/include/video/avi/codec.hpp index 8abc3c5e..c8046e08 100644 --- a/include/video/avi/codec.hpp +++ b/include/video/avi/codec.hpp @@ -94,6 +94,13 @@ struct avi_video_codec * Returns: The packet. */ virtual avi_packet getpacket() = 0; +/** + * Send performance counters. + * + * Parameter b: Amount of busywaiting by emulator. + * Parameter w: Amount of workwaiting by dumper. + */ + virtual void send_performance_counters(uint64_t b, uint64_t w); }; /** diff --git a/src/library/workthread.cpp b/src/library/workthread.cpp index 6afab0a2..ab3aeb91 100644 --- a/src/library/workthread.cpp +++ b/src/library/workthread.cpp @@ -1,5 +1,16 @@ #include "library/workthread.hpp" #include +#include + +namespace +{ + uint64_t ticks() + { + struct timeval tv; + gettimeofday(&tv, NULL); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; + } +} struct worker_thread_reflector { @@ -15,6 +26,8 @@ worker_thread::worker_thread() reflector = NULL; workflag = 0; busy = false; + waitamt_busy = 0; + waitamt_work = 0; exception_caught = false; exception_oom = false; joined = false; @@ -58,8 +71,12 @@ void worker_thread::clear_busy() void worker_thread::wait_busy() { umutex_class h(mutex); - while(busy) - condition.wait(h); + if(busy) { + uint64_t tmp = ticks(); + while(busy) + condition.wait(h); + waitamt_busy += (ticks() - tmp); + } } void worker_thread::rethrow() @@ -90,11 +107,21 @@ uint32_t worker_thread::clear_workflag(uint32_t flag) uint32_t worker_thread::wait_workflag() { umutex_class h(mutex); - while(!workflag) - condition.wait(h); + if(!workflag) { + uint64_t tmp = ticks(); + while(!workflag) + condition.wait(h); + waitamt_work += (ticks() - tmp); + } return workflag; } +std::pair worker_thread::get_wait_count() +{ + umutex_class h(mutex); + return std::make_pair(waitamt_busy, waitamt_work); +} + int worker_thread::operator()(int dummy) { try { diff --git a/src/video/avi.cpp b/src/video/avi.cpp index 297447f3..632bbe5c 100644 --- a/src/video/avi.cpp +++ b/src/video/avi.cpp @@ -127,6 +127,7 @@ namespace uint32_t segframes; uint32_t max_segframes; bool closed; + avi_video_codec* ivcodec; }; #define WORKFLAG_QUEUE_FRAME 1 @@ -137,6 +138,7 @@ namespace avi_worker::avi_worker(const struct avi_info& info) : aviout(info.prefix, *info.vcodec, *info.acodec, info.sample_rate, info.audio_chans) { + ivcodec = info.vcodec; segframes = 0; max_segframes = info.max_frames; fire(); @@ -183,6 +185,8 @@ namespace f.force_break = (segframes == max_segframes && max_segframes > 0); if(f.force_break) segframes = 0; + auto wc = get_wait_count(); + ivcodec->send_performance_counters(wc.first, wc.second); memcpy(&f.data[0], frame, 4 * frame_width * frame_height); frame = NULL; clear_workflag(WORKFLAG_QUEUE_FRAME); diff --git a/src/video/avi/codec.cpp b/src/video/avi/codec.cpp index 00660597..e8bb1527 100644 --- a/src/video/avi/codec.cpp +++ b/src/video/avi/codec.cpp @@ -22,6 +22,10 @@ avi_video_codec::format::format(uint32_t _width, uint32_t _height, uint32_t _com clr_important = 0; } +void avi_video_codec::send_performance_counters(uint64_t b, uint64_t w) +{ +} + avi_audio_codec::format::format(uint16_t tag) { max_bytes_per_sec = 200000;