Files
SingularityViewer/indra/llmessage/aiaverage.cpp
Aleric Inglewood 45e6b7975f First version of HTTP bandwidth throttling.
Adds throttling based on on average bandwidth usage per HTTP service.
Since only HTTP textures are using this, they are still starved by other
services like inventory and mesh dowloads. Also, it will be needed to
move the maximum number of connections per service the to the PerService
class, and dynamically tune them: reducing the number of connections is
the first thing to do when using too much bandwidth.

I also added a graph for HTTP texture bandwidth to the stats floater.
For some reason the average bandwidth (over 1 second) look almost like
scattered noise... weird for something that is averaged...
2013-04-24 22:04:21 +02:00

82 lines
2.8 KiB
C++

/**
* @file aiaverage.cpp
* @brief Implementation of AIAverage
*
* Copyright (c) 2013, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 11/04/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#include "sys.h"
#include "aiaverage.h"
#include "llerror.h" // llassert
void AIAverage::cleanup(U64 clock_tick)
{
// This expression can fail because the curl thread caches the time in
// sTime_10ms for the duration of an entire loop. Therefore, the time can
// go into the next 40ms and a texture fetch worker thread might call
// cleanup() with that time, setting mCurrentClock to a value (one)
// larger than sTime_10ms / 4. Next, the curl thread can continue to call
// this function with the smaller value; in that case just add the new
// data to the current bucket.
//
// Or, this is just the one-time initialization that happens the first
// time this is called. In that case initialize just mCurrentClock:
// the rest is already initialized upon construction.
if (LL_LIKELY(clock_tick > mCurrentClock))
{
// Advance to the next bucket.
++mCurrentBucket;
mCurrentBucket %= mNrOfBuckets;
// Initialize the new bucket.
mData[mCurrentBucket].time = clock_tick;
// Clean up old buckets.
U64 old_time = clock_tick - mNrOfBuckets;
if (LL_UNLIKELY(mTail == mCurrentBucket) || // Extremely unlikely: only happens when data was added EVERY clock tick for the past mNrOfBuckets clock ticks.
mData[mTail].time <= old_time)
{
do
{
mSum -= mData[mTail].sum;
mN -= mData[mTail].n;
mData[mTail].sum = 0;
mData[mTail].n = 0;
++mTail;
if (LL_UNLIKELY(mTail == mNrOfBuckets))
{
mTail = 0;
}
}
while (mData[mTail].time <= old_time);
}
// This was set to zero when mTail passed this point (likely not this call, but a few calls ago).
llassert(mData[mCurrentBucket].sum == 0 &&
mData[mCurrentBucket].n == 0);
}
mCurrentClock = clock_tick;
return;
}