VT: Traffic recorder renewal
1. Switch head & tail definition to prevent confusing
HeadIdx_(n+1) = (HeadIdx_(n) + 1) mod Sizeof(RingBuffer)
X = filled index
O = vacant index
head
O O O X head O O X X
O X O X
O X write O X
O X -----> O X
O X O X
O X X X O X X X
tail tail
2. Preserve data when print information.
The recorder keeps data as possible as it can.
(Current recorder keeps data for 2000ms)
3. Limit traffic recorder size between 4 and 1024 entries.
Bug: 171688417
Change-Id: I7502f09f31d841b04a5d29efb7bb1b904059b3c7
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index dc0ddb9..63b8251 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -62,6 +62,9 @@
static const size_t kMaxPacketSize = 1280;
static char kCNAME[255] = "someone@somewhere";
+static const size_t kTrafficRecorderMaxEntries = 128;
+static const size_t kTrafficRecorderMaxTimeSpanMs = 2000;
+
static int UniformRand(int limit) {
return ((double)rand() * limit) / RAND_MAX;
}
@@ -71,7 +74,8 @@
mFd(dup(fd)),
mLooper(new ALooper),
mReflector(new AHandlerReflector<ARTPWriter>(this)),
- mTrafficRec(new TrafficRecorder<uint32_t, size_t>(128)) {
+ mTrafficRec(new TrafficRecorder<uint32_t, size_t>(
+ kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
CHECK_GE(fd, 0);
mIsIPv6 = false;
@@ -122,7 +126,8 @@
mFd(dup(fd)),
mLooper(new ALooper),
mReflector(new AHandlerReflector<ARTPWriter>(this)),
- mTrafficRec(new TrafficRecorder<uint32_t, size_t>(128)) {
+ mTrafficRec(new TrafficRecorder<uint32_t, size_t>(
+ kTrafficRecorderMaxEntries, kTrafficRecorderMaxTimeSpanMs)) {
CHECK_GE(fd, 0);
mIsIPv6 = false;
diff --git a/media/libstagefright/rtsp/TrafficRecorder.h b/media/libstagefright/rtsp/TrafficRecorder.h
index f8e7c03..a7b2a3c 100644
--- a/media/libstagefright/rtsp/TrafficRecorder.h
+++ b/media/libstagefright/rtsp/TrafficRecorder.h
@@ -27,19 +27,23 @@
template <class Time, class Bytes>
class TrafficRecorder : public RefBase {
private:
+ constexpr static size_t kMinNumEntries = 4;
+ constexpr static size_t kMaxNumEntries = 1024;
+
size_t mSize;
size_t mSizeMask;
Time *mTimeArray = NULL;
Bytes *mBytesArray = NULL;
- size_t mHeadIdx = 0;
- size_t mTailIdx = 0;
+ size_t mHeadIdx;
+ size_t mTailIdx;
- Time mClock = 0;
- Time mLastTimeOfPrint = 0;
- Bytes mAccuBytesOfPrint = 0;
+ int mLastReadIdx;
+
+ const Time mRecordLimit;
+ Time mClock;
+ Time mLastTimeOfPrint;
public:
- TrafficRecorder();
- TrafficRecorder(size_t size);
+ TrafficRecorder(size_t size, Time accuTimeLimit);
virtual ~TrafficRecorder();
void init();
@@ -53,18 +57,19 @@
};
template <class Time, class Bytes>
-TrafficRecorder<Time, Bytes>::TrafficRecorder() {
- TrafficRecorder(128);
-}
-
-template <class Time, class Bytes>
-TrafficRecorder<Time, Bytes>::TrafficRecorder(size_t size) {
- size_t exp;
- for (exp = 0; exp < 32; exp++) {
- if (size <= (1ul << exp)) {
- break;
- }
+TrafficRecorder<Time, Bytes>::TrafficRecorder(size_t size, Time recordLimit)
+ : mRecordLimit(recordLimit) {
+ if (size > kMaxNumEntries) {
+ LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+ size = kMaxNumEntries;
+ } else if (size < kMinNumEntries) {
+ LOG(VERBOSE) << "Limiting TrafficRecorder size to " << kMaxNumEntries;
+ size = kMinNumEntries;
}
+
+ size_t exp = ((sizeof(size_t) == 8) ?
+ 64 - __builtin_clzl(size - 1) :
+ 32 - __builtin_clz(size - 1));
mSize = (1ul << exp); // size = 2^exp
mSizeMask = mSize - 1;
@@ -84,9 +89,14 @@
template <class Time, class Bytes>
void TrafficRecorder<Time, Bytes>::init() {
mHeadIdx = 0;
- mTailIdx = 0;
- mTimeArray[0] = 0;
- mBytesArray[0] = 0;
+ mTailIdx = mSizeMask;
+ for (int i = 0 ; i < mSize ; i++) {
+ mTimeArray[i] = 0;
+ mBytesArray[i] = 0;
+ }
+ mLastReadIdx = 0;
+ mLastTimeOfPrint = 0;
+ mClock = 0;
}
template <class Time, class Bytes>
@@ -96,53 +106,64 @@
template <class Time, class Bytes>
Bytes TrafficRecorder<Time, Bytes>::readBytesForLastPeriod(Time period) {
- Bytes bytes = 0;
+ // Not enough data
+ if (period > mClock)
+ return 0;
- size_t i = mTailIdx;
- while (i != mHeadIdx) {
- LOG(VERBOSE) << "READ " << i << " time " << mTimeArray[i] << " \t EndOfPeriod " << mClock - period;
+ Bytes bytes = 0;
+ int i = mHeadIdx;
+ while (i != mTailIdx) {
+ LOG(VERBOSE) << "READ " << i << " time " << mTimeArray[i]
+ << " \t EndOfPeriod " << mClock - period
+ << "\t\t Bytes:" << mBytesArray[i] << "\t\t Accu: " << bytes;
if (mTimeArray[i] < mClock - period) {
break;
}
bytes += mBytesArray[i];
- i = (i + mSize - 1) & mSizeMask;
+ i = (i - 1) & mSizeMask;
}
- mHeadIdx = i;
+ mLastReadIdx = (i + 1) & mSizeMask;
+
return bytes;
}
template <class Time, class Bytes>
void TrafficRecorder<Time, Bytes>::writeBytes(Bytes bytes) {
- size_t writeIdx;
- if (mClock == mTimeArray[mTailIdx]) {
- writeIdx = mTailIdx;
+ int writeIdx;
+ if (mClock == mTimeArray[mHeadIdx]) {
+ writeIdx = mHeadIdx;
mBytesArray[writeIdx] += bytes;
} else {
- writeIdx = (mTailIdx + 1) % mSize;
+ writeIdx = (mHeadIdx + 1) & mSizeMask;
mTimeArray[writeIdx] = mClock;
mBytesArray[writeIdx] = bytes;
}
LOG(VERBOSE) << "WRITE " << writeIdx << " time " << mClock;
- if (writeIdx == mHeadIdx) {
- LOG(WARNING) << "Traffic recorder size exceeded at " << mHeadIdx;
- mHeadIdx = (mHeadIdx + 1) & mSizeMask;
+ if (writeIdx == mTailIdx) {
+ mTailIdx = (mTailIdx + 1) & mSizeMask;
}
- mTailIdx = writeIdx;
- mAccuBytesOfPrint += bytes;
+ mHeadIdx = writeIdx;
}
template <class Time, class Bytes>
void TrafficRecorder<Time, Bytes>::printAccuBitsForLastPeriod(Time period, Time unit) {
- Time duration = mClock - mLastTimeOfPrint;
- float numOfUnit = (float)duration / unit;
- if (duration > period) {
- ALOGD("Actual Tx period %.0f ms \t %.0f Bits/Unit",
- numOfUnit * 1000.f, mAccuBytesOfPrint * 8.f / numOfUnit);
- mLastTimeOfPrint = mClock;
- mAccuBytesOfPrint = 0;
- init();
+ Time timeSinceLastPrint = mClock - mLastTimeOfPrint;
+ if (timeSinceLastPrint < period)
+ return;
+
+ Bytes sum = readBytesForLastPeriod(period);
+ Time readPeriod = mClock - mTimeArray[mLastReadIdx];
+
+ float numOfUnit = (float)(readPeriod) / (unit + FLT_MIN);
+ ALOGD("Actual Tx period %.3f unit \t %.0f bytes (%.0f Kbits)/Unit",
+ numOfUnit, sum / numOfUnit, sum * 8.f / numOfUnit / 1000.f);
+ mLastTimeOfPrint = mClock;
+
+ if (mClock - mTimeArray[mTailIdx] < mRecordLimit) {
+ // Size is not enough to record bytes for mRecordLimit period
+ ALOGW("Traffic recorder size is not enough. mRecordLimit %d", mRecordLimit);
}
}