Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Improved input rate calculation. #763

Merged
merged 1 commit into from
Jul 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 52 additions & 60 deletions srtcore/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,30 @@ modified by
using namespace std;
using namespace srt_logging;

CSndBuffer::CSndBuffer(int size, int mss):
m_BufLock(),
m_pBlock(NULL),
m_pFirstBlock(NULL),
m_pCurrBlock(NULL),
m_pLastBlock(NULL),
m_pBuffer(NULL),
m_iNextMsgNo(1),
m_iSize(size),
m_iMSS(mss),
m_iCount(0)
,m_iBytesCount(0)
,m_ullLastOriginTime_us(0)
CSndBuffer::CSndBuffer(int size, int mss)
: m_BufLock()
, m_pBlock(NULL)
, m_pFirstBlock(NULL)
, m_pCurrBlock(NULL)
, m_pLastBlock(NULL)
, m_pBuffer(NULL)
, m_iNextMsgNo(1)
, m_iSize(size)
, m_iMSS(mss)
, m_iCount(0)
, m_iBytesCount(0)
, m_ullLastOriginTime_us(0)
#ifdef SRT_ENABLE_SNDBUFSZ_MAVG
,m_LastSamplingTime(0)
,m_iCountMAvg(0)
,m_iBytesCountMAvg(0)
,m_TimespanMAvg(0)
, m_LastSamplingTime(0)
, m_iCountMAvg(0)
, m_iBytesCountMAvg(0)
, m_TimespanMAvg(0)
#endif
,m_iInRatePktsCount(0)
,m_iInRateBytesCount(0)
,m_InRateStartTime(0)
,m_InRatePeriod(CUDT::SND_INPUTRATE_FAST_START_US) // 0.5 sec (fast start)
,m_iInRateBps(CUDT::SND_INPUTRATE_INITIAL_BPS)
, m_iInRatePktsCount(0)
, m_iInRateBytesCount(0)
, m_InRateStartTime(0)
, m_InRatePeriod(INPUTRATE_FAST_START_US) // 0.5 sec (fast start)
, m_iInRateBps(INPUTRATE_INITIAL_BYTESPS)
{
// initial physical buffer of "size"
m_pBuffer = new Buffer;
Expand Down Expand Up @@ -155,7 +155,7 @@ void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order, uint6
increase();
}

uint64_t time = CTimer::getTime();
const uint64_t time = CTimer::getTime();
int32_t inorder = order ? MSGNO_PACKET_INORDER::mask : 0;

HLOGC(dlog.Debug, log << CONID() << "addBuffer: adding "
Expand Down Expand Up @@ -202,7 +202,7 @@ void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order, uint6
m_iBytesCount += len;
m_ullLastOriginTime_us = time;

updInputRate(time, size, len);
updateInputRate(time, size, len);

#ifdef SRT_ENABLE_SNDBUFSZ_MAVG
updAvgBufSize(time);
Expand All @@ -224,54 +224,46 @@ void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order, uint6

void CSndBuffer::setInputRateSmpPeriod(int period)
{
m_InRatePeriod = (uint64_t)period; //(usec) 0=no input rate calculation
m_InRatePeriod = (uint64_t)period; //(usec) 0=no input rate calculation
}

void CSndBuffer::updInputRate(uint64_t time, int pkts, int bytes)
void CSndBuffer::updateInputRate(uint64_t time, int pkts, int bytes)
{
if (m_InRatePeriod == 0)
;//no input rate calculation
else if (m_InRateStartTime == 0)
m_InRateStartTime = time;
else
{
m_iInRatePktsCount += pkts;
m_iInRateBytesCount += bytes;
if ((time - m_InRateStartTime) > m_InRatePeriod) {
//Required Byte/sec rate (payload + headers)
m_iInRateBytesCount += (m_iInRatePktsCount * CPacket::SRT_DATA_HDR_SIZE);
m_iInRateBps = (int)(((int64_t)m_iInRateBytesCount * 1000000) / (time - m_InRateStartTime));
HLOGC(dlog.Debug, log << "updInputRate: pkts:" << m_iInRateBytesCount << " bytes:" << m_iInRatePktsCount
<< " rate=" << (m_iInRateBps*8)/1000
<< "kbps interval=" << (time - m_InRateStartTime));
m_iInRatePktsCount = 0;
m_iInRateBytesCount = 0;
m_InRateStartTime = time;
}
}
}
//no input rate calculation
if (m_InRatePeriod == 0)
return;

int CSndBuffer::getInputRate(ref_t<uint64_t> r_period)
{
uint64_t& period = *r_period;
uint64_t time = CTimer::getTime();
if (m_InRateStartTime == 0)
{
m_InRateStartTime = time;
return;
}

m_iInRatePktsCount += pkts;
m_iInRateBytesCount += bytes;

// Trigger early update in fast start mode
const bool early_update = (m_InRatePeriod < INPUTRATE_RUNNING_US)
&& (m_iInRatePktsCount > INPUTRATE_MAX_PACKETS);

if ((m_InRatePeriod != 0)
&& (m_InRateStartTime != 0)
&& ((time - m_InRateStartTime) > m_InRatePeriod))
const uint64_t period_us = (time - m_InRateStartTime);
if (early_update || period_us > m_InRatePeriod)
{
//include packet headers: SRT + UDP + IP
int64_t llBytesCount = (int64_t)m_iInRateBytesCount + (m_iInRatePktsCount * (CPacket::HDR_SIZE + CPacket::UDP_HDR_SIZE));
//Byte/sec rate
m_iInRateBps = (int)((llBytesCount * 1000000) / (time - m_InRateStartTime));
//Required Byte/sec rate (payload + headers)
m_iInRateBytesCount += (m_iInRatePktsCount * CPacket::SRT_DATA_HDR_SIZE);
m_iInRateBps = (int)(((int64_t)m_iInRateBytesCount * 1000000) / period_us);
HLOGC(dlog.Debug, log << "updateInputRate: pkts:" << m_iInRateBytesCount << " bytes:" << m_iInRatePktsCount
<< " rate=" << (m_iInRateBps*8)/1000
<< "kbps interval=" << period_us);
m_iInRatePktsCount = 0;
m_iInRateBytesCount = 0;
m_InRateStartTime = time;

setInputRateSmpPeriod(INPUTRATE_RUNNING_US);
}
period = m_InRatePeriod;
return(m_iInRateBps);
}


int CSndBuffer::addBufferFromFile(fstream& ifs, int len)
{
int size = len / m_iMSS;
Expand Down
31 changes: 28 additions & 3 deletions srtcore/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,37 @@ class CSndBuffer
#endif /* SRT_ENABLE_SNDBUFSZ_MAVG */
int getCurrBufSize(ref_t<int> bytes, ref_t<int> timespan);

int getInputRate(ref_t<uint64_t> period);
void updInputRate(uint64_t time, int pkts, int bytes);
void setInputRateSmpPeriod(int period);
uint64_t getInRatePeriod() const { return m_InRatePeriod; }

/// Retrieve input bitrate in bytes per second
int getInputRate() const { return m_iInRateBps; }

/// Update input rate calculation.
/// @param [in] time current time in microseconds
/// @param [in] pkts number of packets newly added to the buffer
/// @param [in] bytes number of payload bytes in those newly added packets
///
/// @return Current size of the data in the sending list.
void updateInputRate(uint64_t time, int pkts = 0, int bytes = 0);


void resetInputRateSmpPeriod(bool disable = false)
{
setInputRateSmpPeriod(disable ? 0 : INPUTRATE_FAST_START_US);
}


private:

void increase();
void setInputRateSmpPeriod(int period);

private: // Constants

static const uint64_t INPUTRATE_FAST_START_US = 500000; // 500 ms
static const uint64_t INPUTRATE_RUNNING_US = 1000000; // 1000 ms
static const int64_t INPUTRATE_MAX_PACKETS = 2000; // ~ 21 Mbps of 1316 bytes payload
static const int INPUTRATE_INITIAL_BYTESPS = BW_INFINITE;

private:
pthread_mutex_t m_BufLock; // used to synchronize buffer operation
Expand Down
3 changes: 2 additions & 1 deletion srtcore/congctl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ class LiveCC: public SrtCongestionControlBase
// packet = payload + header
const double pktsize = (double) m_zSndAvgPayloadSize + CPacket::SRT_DATA_HDR_SIZE;
m_dPktSndPeriod = 1000 * 1000.0 * (pktsize / m_llSndMaxBW);
HLOGC(mglog.Debug, log << "LiveCC: sending period updated: " << m_zSndAvgPayloadSize);
HLOGC(mglog.Debug, log << "LiveCC: sending period updated: " << m_dPktSndPeriod
<< " (pktsize=" << pktsize << ", bw=" << m_llSndMaxBW);
}

void setMaxBW(int64_t maxbw)
Expand Down
17 changes: 5 additions & 12 deletions srtcore/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6250,7 +6250,9 @@ void CUDT::updateCC(ETransmissionEvent evt, EventVariant arg)
}
else
{
m_pSndBuffer->setInputRateSmpPeriod(bw == 0 ? SND_INPUTRATE_FAST_START_US: 0);
// No need to calculate input reate if the bandwidth is set
const bool disable_in_rate_calc = (bw != 0);
m_pSndBuffer->resetInputRateSmpPeriod(disable_in_rate_calc);
}

HLOGC(mglog.Debug, log << "updateCC/TEV_INIT: updating BW=" << m_llMaxBW
Expand All @@ -6267,12 +6269,8 @@ void CUDT::updateCC(ETransmissionEvent evt, EventVariant arg)
// This requests internal input rate sampling.
if (m_llMaxBW == 0 && m_llInputBW == 0)
{
uint64_t period;
int64_t inputbw = m_pSndBuffer->getInputRate(Ref(period)); //Auto input rate

// NOTE:
// 'period' here is set to the value that was previously set by
// m_pSndBuffer->setInputRateSmpPeriod().
// Get auto-calculated input rate, Bytes per second
const int64_t inputbw = m_pSndBuffer->getInputRate();

/*
* On blocked transmitter (tx full) and until connection closes,
Expand All @@ -6283,11 +6281,6 @@ void CUDT::updateCC(ETransmissionEvent evt, EventVariant arg)
*/
if (inputbw != 0)
m_CongCtl->updateBandwidth(0, withOverhead(inputbw)); //Bytes/sec

CGuard::enterCS(m_StatsLock);
if ((m_stats.sentTotal > SND_INPUTRATE_MAX_PACKETS) && (period < SND_INPUTRATE_RUNNING_US))
m_pSndBuffer->setInputRateSmpPeriod(SND_INPUTRATE_RUNNING_US); //1 sec period after fast start
CGuard::leaveCS(m_StatsLock);
}
}

Expand Down
7 changes: 0 additions & 7 deletions srtcore/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,6 @@ class CUDT
static const uint64_t COMM_KEEPALIVE_PERIOD_US = 1*1000*1000;
static const int32_t COMM_SYN_INTERVAL_US = 10*1000;

// Input rate constants
static const uint64_t
SND_INPUTRATE_FAST_START_US = 500*1000,
SND_INPUTRATE_RUNNING_US = 1*1000*1000;
static const int64_t SND_INPUTRATE_MAX_PACKETS = 2000;
static const int SND_INPUTRATE_INITIAL_BPS = 10000000/8; // 10 Mbps (1.25 MBps)

int handshakeVersion()
{
return m_ConnRes.m_iVersion;
Expand Down