diff --git a/srtcore/common.h b/srtcore/common.h index 56ddf2748..d23c22022 100644 --- a/srtcore/common.h +++ b/srtcore/common.h @@ -1477,6 +1477,11 @@ struct MetricOp { m = 0; } + + static bool is_zero(const METRIC_TYPE& m) + { + return m == 0; + } }; template <> @@ -1489,4 +1494,19 @@ struct MetricOp } }; +template <> +struct MetricOp +{ + typedef srt::sync::steady_clock::duration duration; + static bool is_zero(const duration& m) + { + return m == duration::zero(); + } + + static void Clear(duration& m) + { + m = duration::zero(); + } +}; + #endif diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 49da9a79a..076293d47 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -1493,6 +1493,8 @@ void CUDT::clearData() m_stats.traceRcvBytesUndecrypt = 0; m_stats.sndDuration = m_stats.m_sndDurationTotal = 0; + m_stats.tdAverageResponseTime.Init(); + m_stats.tdMaxResponseTime.Init(); } // Resetting these data because this happens when agent isn't connected. @@ -7623,6 +7625,11 @@ void CUDT::bstats(CBytePerfMon *perf, bool clear, bool instantaneous) perf->msRcvBuf = 0; } + perf->msAvgResponseTimeTotal = count_milliseconds(m_stats.tdAverageResponseTime.total); + perf->msMaxResponseTimeTotal = count_milliseconds(m_stats.tdMaxResponseTime.total); + perf->msAvgResponseTime = count_milliseconds(m_stats.tdAverageResponseTime.local); + perf->msMaxResponseTime = count_milliseconds(m_stats.tdMaxResponseTime.local); + if (clear) { m_stats.traceSndDrop = 0; @@ -7649,6 +7656,8 @@ void CUDT::bstats(CBytePerfMon *perf, bool clear, bool instantaneous) m_stats.rcvFilterLoss = 0; m_stats.tsLastSampleTime = currtime; + m_stats.tdAverageResponseTime.Clear(); + m_stats.tdMaxResponseTime.Clear(); } } @@ -8698,7 +8707,7 @@ void CUDT::processCtrl(const CPacket &ctrlpkt) // Just heard from the peer, reset the expiration count. m_iEXPCount = 1; const steady_clock::time_point currtime = steady_clock::now(); - m_tsLastRspTime = currtime; + recordResponseTime(currtime); bool using_rexmit_flag = m_bPeerRexmitFlag; HLOGC(inlog.Debug, @@ -9614,7 +9623,7 @@ int CUDT::processData(CUnit* in_unit) // Just heard from the peer, reset the expiration count. m_iEXPCount = 1; - m_tsLastRspTime = steady_clock::now(); + recordResponseTime(steady_clock::now()); const bool need_tsbpd = m_bTsbPd || m_bGroupTsbPd; diff --git a/srtcore/core.h b/srtcore/core.h index cc4d8ccf2..d5f5fd8cc 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -138,6 +138,51 @@ enum SeqPairItems SEQ_BEGIN = 0, SEQ_END = 1, SEQ_SIZE = 2 }; +template +struct AverageMetricUsage: public MetricUsage +{ + using MetricUsage::Clear; + using MetricUsage::Init; + using MetricUsage::local; + using MetricUsage::total; + + void Update(METRIC_TYPE value) + { + if (MetricOp::is_zero(local)) + local = value; + else + { + local = (local + value)/2; + } + + if (MetricOp::is_zero(total)) + total = value; + else + { + total = (total + value)/2; + } + } +}; + + +template +struct MaxMetricUsage: public MetricUsage +{ + using MetricUsage::Clear; + using MetricUsage::Init; + using MetricUsage::local; + using MetricUsage::total; + + void Update(METRIC_TYPE value) + { + if (value > local) + local = value; + + if (value > total) + total = value; + } +}; + #if ENABLE_EXPERIMENTAL_BONDING struct SRT_SocketOptionObject @@ -1173,8 +1218,30 @@ class CUDT int64_t sndDuration; // real time for sending time_point sndDurationCounter; // timers to record the sending Duration + + AverageMetricUsage tdAverageResponseTime; + MaxMetricUsage tdMaxResponseTime; } m_stats; + /// This function records the passed current time as the last response time. + /// Before doing it, however, it checks if there exist any previous such time + /// and updates statistics accordingly. + void recordResponseTime(const time_point& now) + { + using namespace srt::sync; + + if (!is_zero(m_tsLastRspTime)) + { + duration td = now - m_tsLastRspTime; + enterCS(m_StatsLock); + m_stats.tdAverageResponseTime.Update(td); + m_stats.tdMaxResponseTime.Update(td); + leaveCS(m_StatsLock); + } + + m_tsLastRspTime = now; + } + public: static const int SELF_CLOCK_INTERVAL = 64; // ACK interval for self-clocking static const int SEND_LITE_ACK = sizeof(int32_t); // special size for ack containing only ack seq diff --git a/srtcore/srt.h b/srtcore/srt.h index f3a5becdc..99e7afcd8 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -403,12 +403,16 @@ struct CBytePerfMon int64_t pktRecvUniqueTotal; // total number of packets to be received by the application uint64_t byteSentUniqueTotal; // total number of data bytes, sent by the application uint64_t byteRecvUniqueTotal; // total number of data bytes to be received by the application + uint32_t msAvgResponseTimeTotal; + uint32_t msMaxResponseTimeTotal; // Local int64_t pktSentUnique; // number of data packets sent by the application int64_t pktRecvUnique; // number of packets to be received by the application uint64_t byteSentUnique; // number of data bytes, sent by the application uint64_t byteRecvUnique; // number of data bytes to be received by the application + uint32_t msAvgResponseTime; + uint32_t msMaxResponseTime; }; ////////////////////////////////////////////////////////////////////////////////