SRT链路统计信息接口(Link Statistics)

一.接口名称

// perfmon with Byte counters for better bitrate estimation.
SRT_API int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear);
// permon with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes.
SRT_API int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous);

int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear) { return CUDT::bstats(u, perf, 0!=  clear); }
int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous) { return CUDT::bstats(u, perf, 0!=  clear, 0!= instantaneous); }

二.调用流程

int SrtTarget::Write(const char* data, size_t size, ostream &out_stats)
{
    static unsigned long counter = 1;

    int stat = srt_sendmsg2(m_sock, data, (int) size, nullptr);
    if (stat == SRT_ERROR)
    {
        return stat;
    }

    const bool need_bw_report = transmit_bw_report && (counter % transmit_bw_report) == transmit_bw_report - 1;
    const bool need_stats_report = transmit_stats_report && (counter % transmit_stats_report) == transmit_stats_report - 1;

    if (need_bw_report || need_stats_report)
    {
        CBytePerfMon perf;
        srt_bstats(m_sock, &perf, need_stats_report && !transmit_total_stats);
        if (stats_writer != nullptr)
        {
            if (need_bw_report)
                cerr << stats_writer->WriteBandwidth(perf.mbpsBandwidth) << std::flush;
            if (need_stats_report)
                out_stats << stats_writer->WriteStats(m_sock, perf) << std::flush;
        }
    }
    ++counter;
    return stat;
}

int SrtSource::Read(size_t chunk, bytevector& data, ostream &out_stats)
{
    static unsigned long counter = 1;

    if (data.size() < chunk)
        data.resize(chunk);

    const int stat = srt_recvmsg(m_sock, data.data(), (int) chunk);
    if (stat <= 0)
    {
        data.clear();
        return stat;
    }

    chunk = size_t(stat);
    if (chunk < data.size())
        data.resize(chunk);

    const bool need_bw_report = transmit_bw_report && (counter % transmit_bw_report) == transmit_bw_report - 1;
    const bool need_stats_report = transmit_stats_report && (counter % transmit_stats_report) == transmit_stats_report - 1;

    if (need_bw_report || need_stats_report)
    {
        CBytePerfMon perf;
        srt_bstats(m_sock, &perf, need_stats_report && !transmit_total_stats);
        if (stats_writer != nullptr) 
        {
            if (need_bw_report)
                cerr << stats_writer->WriteBandwidth(perf.mbpsBandwidth) << std::flush;
            if (need_stats_report)
                out_stats << stats_writer->WriteStats(m_sock, perf) << std::flush;
        }
    }
    ++counter;
    return stat;
}

三.接口内部实现

void CUDT::bstats(CBytePerfMon *perf, bool clear, bool instantaneous)
{
    if (!m_bConnected)
        throw CUDTException(MJ_CONNECTION, MN_NOCONN, 0);
    if (m_bBroken || m_bClosing)
        throw CUDTException(MJ_CONNECTION, MN_CONNLOST, 0);

    CGuard statsguard(m_StatsLock);

    uint64_t currtime = CTimer::getTime();
    perf->msTimeStamp = (currtime - m_stats.startTime) / 1000;

    perf->pktSent              = m_stats.traceSent;
    perf->pktRecv              = m_stats.traceRecv;
    perf->pktSndLoss           = m_stats.traceSndLoss;
    perf->pktRcvLoss           = m_stats.traceRcvLoss;
    perf->pktRetrans           = m_stats.traceRetrans;
    perf->pktRcvRetrans        = m_stats.traceRcvRetrans;
    perf->pktSentACK           = m_stats.sentACK;
    perf->pktRecvACK           = m_stats.recvACK;
    perf->pktSentNAK           = m_stats.sentNAK;
    perf->pktRecvNAK           = m_stats.recvNAK;
    perf->usSndDuration        = m_stats.sndDuration;
    perf->pktReorderDistance   = m_stats.traceReorderDistance;
    perf->pktReorderTolerance  = m_iReorderTolerance;
    perf->pktRcvAvgBelatedTime = m_stats.traceBelatedTime;
    perf->pktRcvBelated        = m_stats.traceRcvBelated;

    perf->pktSndFilterExtra  = m_stats.sndFilterExtra;
    perf->pktRcvFilterExtra  = m_stats.rcvFilterExtra;
    perf->pktRcvFilterSupply = m_stats.rcvFilterSupply;
    perf->pktRcvFilterLoss   = m_stats.rcvFilterLoss;

    /* perf byte counters include all headers (SRT+UDP+IP) */
    const int pktHdrSize = CPacket::HDR_SIZE + CPacket::UDP_HDR_SIZE;
    perf->byteSent       = m_stats.traceBytesSent + (m_stats.traceSent * pktHdrSize);
    perf->byteRecv       = m_stats.traceBytesRecv + (m_stats.traceRecv * pktHdrSize);
    perf->byteRetrans    = m_stats.traceBytesRetrans + (m_stats.traceRetrans * pktHdrSize);
#ifdef SRT_ENABLE_LOSTBYTESCOUNT
    perf->byteRcvLoss = m_stats.traceRcvBytesLoss + (m_stats.traceRcvLoss * pktHdrSize);
#endif

    perf->pktSndDrop  = m_stats.traceSndDrop;
    perf->pktRcvDrop  = m_stats.traceRcvDrop + m_stats.traceRcvUndecrypt;
    perf->byteSndDrop = m_stats.traceSndBytesDrop + (m_stats.traceSndDrop * pktHdrSize);
    perf->byteRcvDrop =
        m_stats.traceRcvBytesDrop + (m_stats.traceRcvDrop * pktHdrSize) + m_stats.traceRcvBytesUndecrypt;
    perf->pktRcvUndecrypt  = m_stats.traceRcvUndecrypt;
    perf->byteRcvUndecrypt = m_stats.traceRcvBytesUndecrypt;

    perf->pktSentTotal       = m_stats.sentTotal;
    perf->pktRecvTotal       = m_stats.recvTotal;
    perf->pktSndLossTotal    = m_stats.sndLossTotal;
    perf->pktRcvLossTotal    = m_stats.rcvLossTotal;
    perf->pktRetransTotal    = m_stats.retransTotal;
    perf->pktSentACKTotal    = m_stats.sentACKTotal;
    perf->pktRecvACKTotal    = m_stats.recvACKTotal;
    perf->pktSentNAKTotal    = m_stats.sentNAKTotal;
    perf->pktRecvNAKTotal    = m_stats.recvNAKTotal;
    perf->usSndDurationTotal = m_stats.m_sndDurationTotal;

    perf->byteSentTotal           = m_stats.bytesSentTotal + (m_stats.sentTotal * pktHdrSize);
    perf->byteRecvTotal           = m_stats.bytesRecvTotal + (m_stats.recvTotal * pktHdrSize);
    perf->byteRetransTotal        = m_stats.bytesRetransTotal + (m_stats.retransTotal * pktHdrSize);
    perf->pktSndFilterExtraTotal  = m_stats.sndFilterExtraTotal;
    perf->pktRcvFilterExtraTotal  = m_stats.rcvFilterExtraTotal;
    perf->pktRcvFilterSupplyTotal = m_stats.rcvFilterSupplyTotal;
    perf->pktRcvFilterLossTotal   = m_stats.rcvFilterLossTotal;

#ifdef SRT_ENABLE_LOSTBYTESCOUNT
    perf->byteRcvLossTotal = m_stats.rcvBytesLossTotal + (m_stats.rcvLossTotal * pktHdrSize);
#endif
    perf->pktSndDropTotal  = m_stats.sndDropTotal;
    perf->pktRcvDropTotal  = m_stats.rcvDropTotal + m_stats.m_rcvUndecryptTotal;
    perf->byteSndDropTotal = m_stats.sndBytesDropTotal + (m_stats.sndDropTotal * pktHdrSize);
    perf->byteRcvDropTotal =
        m_stats.rcvBytesDropTotal + (m_stats.rcvDropTotal * pktHdrSize) + m_stats.m_rcvBytesUndecryptTotal;
    perf->pktRcvUndecryptTotal  = m_stats.m_rcvUndecryptTotal;
    perf->byteRcvUndecryptTotal = m_stats.m_rcvBytesUndecryptTotal;
    //<

    double interval = double(currtime - m_stats.lastSampleTime);

    //>mod
    perf->mbpsSendRate = double(perf->byteSent) * 8.0 / interval;
    perf->mbpsRecvRate = double(perf->byteRecv) * 8.0 / interval;
    //<

    perf->usPktSndPeriod      = m_ullInterval_tk / double(m_ullCPUFrequency);
    perf->pktFlowWindow       = m_iFlowWindowSize;
    perf->pktCongestionWindow = (int)m_dCongestionWindow;
    perf->pktFlightSize       = CSeqNo::seqlen(m_iSndLastAck, CSeqNo::incseq(m_iSndCurrSeqNo)) - 1;
    perf->msRTT               = (double)m_iRTT / 1000.0;
    //>new
    perf->msSndTsbPdDelay = m_bPeerTsbPd ? m_iPeerTsbPdDelay_ms : 0;
    perf->msRcvTsbPdDelay = m_bTsbPd ? m_iTsbPdDelay_ms : 0;
    perf->byteMSS         = m_iMSS;

    perf->mbpsMaxBW = m_llMaxBW > 0 ? Bps2Mbps(m_llMaxBW) : m_CongCtl.ready() ? Bps2Mbps(m_CongCtl->sndBandwidth()) : 0;

    //<
    uint32_t availbw = (uint64_t)(m_iBandwidth == 1 ? m_RcvTimeWindow.getBandwidth() : m_iBandwidth);

    perf->mbpsBandwidth = Bps2Mbps(availbw * (m_iMaxSRTPayloadSize + pktHdrSize));

    if (pthread_mutex_trylock(&m_ConnectionLock) == 0)
    {
        if (m_pSndBuffer)
        {
#ifdef SRT_ENABLE_SNDBUFSZ_MAVG
            if (instantaneous)
            {
                /* Get instant SndBuf instead of moving average for application-based Algorithm
                   (such as NAE) in need of fast reaction to network condition changes. */
                perf->pktSndBuf = m_pSndBuffer->getCurrBufSize(Ref(perf->byteSndBuf), Ref(perf->msSndBuf));
            }
            else
            {
                perf->pktSndBuf = m_pSndBuffer->getAvgBufSize(Ref(perf->byteSndBuf), Ref(perf->msSndBuf));
            }
#else
            perf->pktSndBuf = m_pSndBuffer->getCurrBufSize(Ref(perf->byteSndBuf), Ref(perf->msSndBuf));
#endif
            perf->byteSndBuf += (perf->pktSndBuf * pktHdrSize);
            //<
            perf->byteAvailSndBuf = (m_iSndBufSize - perf->pktSndBuf) * m_iMSS;
        }
        else
        {
            perf->byteAvailSndBuf = 0;
            // new>
            perf->pktSndBuf  = 0;
            perf->byteSndBuf = 0;
            perf->msSndBuf   = 0;
            //<
        }

        if (m_pRcvBuffer)
        {
            perf->byteAvailRcvBuf = m_pRcvBuffer->getAvailBufSize() * m_iMSS;
            // new>
#ifdef SRT_ENABLE_RCVBUFSZ_MAVG
            if (instantaneous) // no need for historical API for Rcv side
            {
                perf->pktRcvBuf = m_pRcvBuffer->getRcvDataSize(perf->byteRcvBuf, perf->msRcvBuf);
            }
            else
            {
                perf->pktRcvBuf = m_pRcvBuffer->getRcvAvgDataSize(perf->byteRcvBuf, perf->msRcvBuf);
            }
#else
            perf->pktRcvBuf = m_pRcvBuffer->getRcvDataSize(perf->byteRcvBuf, perf->msRcvBuf);
#endif
            //<
        }
        else
        {
            perf->byteAvailRcvBuf = 0;
            // new>
            perf->pktRcvBuf  = 0;
            perf->byteRcvBuf = 0;
            perf->msRcvBuf   = 0;
            //<
        }

        pthread_mutex_unlock(&m_ConnectionLock);
    }
    else
    {
        perf->byteAvailSndBuf = 0;
        perf->byteAvailRcvBuf = 0;
        // new>
        perf->pktSndBuf  = 0;
        perf->byteSndBuf = 0;
        perf->msSndBuf   = 0;

        perf->byteRcvBuf = 0;
        perf->msRcvBuf   = 0;
        //<
    }

    if (clear)
    {
        m_stats.traceSndDrop           = 0;
        m_stats.traceRcvDrop           = 0;
        m_stats.traceSndBytesDrop      = 0;
        m_stats.traceRcvBytesDrop      = 0;
        m_stats.traceRcvUndecrypt      = 0;
        m_stats.traceRcvBytesUndecrypt = 0;
        // new>
        m_stats.traceBytesSent = m_stats.traceBytesRecv = m_stats.traceBytesRetrans = 0;
        //<
        m_stats.traceSent = m_stats.traceRecv = m_stats.traceSndLoss = m_stats.traceRcvLoss = m_stats.traceRetrans =
            m_stats.sentACK = m_stats.recvACK = m_stats.sentNAK = m_stats.recvNAK = 0;
        m_stats.sndDuration                                                       = 0;
        m_stats.traceRcvRetrans                                                   = 0;
        m_stats.traceRcvBelated                                                   = 0;
#ifdef SRT_ENABLE_LOSTBYTESCOUNT
        m_stats.traceRcvBytesLoss = 0;
#endif

        m_stats.sndFilterExtra = 0;
        m_stats.rcvFilterExtra = 0;

        m_stats.rcvFilterSupply = 0;
        m_stats.rcvFilterLoss   = 0;

        m_stats.lastSampleTime = currtime;
    }
}

参考资料:
https://github.com/Haivision/srt
[github releases]: https://github.com/Haivision/srt/releases

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值