00001
00032 #include "linden_common.h"
00033
00034 #include "llthrottle.h"
00035 #include "llmath.h"
00036 #include "lldatapacker.h"
00037 #include "message.h"
00038
00039
00040 LLThrottle::LLThrottle(const F32 rate)
00041 {
00042 mRate = rate;
00043 mAvailable = 0.f;
00044 mLookaheadSecs = 0.25f;
00045 mLastSendTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
00046 }
00047
00048
00049 void LLThrottle::setRate(const F32 rate)
00050 {
00051
00052 mAvailable = getAvailable();
00053 mLastSendTime = LLMessageSystem::getMessageTimeSeconds();
00054 mRate = rate;
00055 }
00056
00057 F32 LLThrottle::getAvailable()
00058 {
00059
00060
00061 F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
00062 return mAvailable + (mRate * elapsed_time);
00063 }
00064
00065 BOOL LLThrottle::checkOverflow(const F32 amount)
00066 {
00067 BOOL retval = TRUE;
00068
00069 F32 lookahead_amount = mRate * mLookaheadSecs;
00070
00071
00072
00073 F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
00074 F32 amount_available = mAvailable + (mRate * elapsed_time);
00075
00076 if ((amount_available >= lookahead_amount) || (amount_available > amount))
00077 {
00078
00079
00080 retval = FALSE;
00081 }
00082
00083 return retval;
00084 }
00085
00086 BOOL LLThrottle::throttleOverflow(const F32 amount)
00087 {
00088 F32 elapsed_time;
00089 F32 lookahead_amount;
00090 BOOL retval = TRUE;
00091
00092 lookahead_amount = mRate * mLookaheadSecs;
00093
00094 F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
00095 elapsed_time = (F32)(mt_sec - mLastSendTime);
00096 mLastSendTime = mt_sec;
00097
00098 mAvailable += mRate * elapsed_time;
00099
00100 if (mAvailable >= lookahead_amount)
00101 {
00102
00103
00104 mAvailable = lookahead_amount;
00105 retval = FALSE;
00106 }
00107 else if (mAvailable > amount)
00108 {
00109
00110 retval = FALSE;
00111 }
00112
00113
00114 mAvailable -= amount;
00115
00116
00117
00118
00119
00120 return retval;
00121 }
00122
00123
00124
00125 const F32 THROTTLE_LOOKAHEAD_TIME = 1.f;
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 F32 gThrottleMaximumBPS[TC_EOF] =
00136 {
00137 150000.f,
00138 170000.f,
00139 34000.f,
00140 34000.f,
00141 446000.f,
00142 446000.f,
00143 220000.f,
00144 };
00145
00146
00147
00148
00149
00150
00151
00152 F32 gThrottleDefaultBPS[TC_EOF] =
00153 {
00154 100000.f,
00155 4000.f,
00156 4000.f,
00157 4000.f,
00158 4000.f,
00159 4000.f,
00160 100000.f,
00161 };
00162
00163
00164
00165
00166 F32 gThrottleMinimumBPS[TC_EOF] =
00167 {
00168 10000.f,
00169 10000.f,
00170 4000.f,
00171 4000.f,
00172 20000.f,
00173 10000.f,
00174 10000.f,
00175 };
00176
00177 const char* THROTTLE_NAMES[TC_EOF] =
00178 {
00179 "Resend ",
00180 "Land ",
00181 "Wind ",
00182 "Cloud ",
00183 "Task ",
00184 "Texture",
00185 "Asset "
00186 };
00187
00188 LLThrottleGroup::LLThrottleGroup()
00189 {
00190 S32 i;
00191 for (i = 0; i < TC_EOF; i++)
00192 {
00193 mThrottleTotal[i] = gThrottleDefaultBPS[i];
00194 mNominalBPS[i] = gThrottleDefaultBPS[i];
00195 }
00196
00197 resetDynamicAdjust();
00198 }
00199
00200 void LLThrottleGroup::packThrottle(LLDataPacker &dp) const
00201 {
00202 S32 i;
00203 for (i = 0; i < TC_EOF; i++)
00204 {
00205 dp.packF32(mThrottleTotal[i], "Throttle");
00206 }
00207 }
00208
00209 void LLThrottleGroup::unpackThrottle(LLDataPacker &dp)
00210 {
00211 S32 i;
00212 for (i = 0; i < TC_EOF; i++)
00213 {
00214 F32 temp_throttle;
00215 dp.unpackF32(temp_throttle, "Throttle");
00216 temp_throttle = llclamp(temp_throttle, 0.f, 2250000.f);
00217 mThrottleTotal[i] = temp_throttle;
00218 if(mThrottleTotal[i] > gThrottleMaximumBPS[i])
00219 {
00220 mThrottleTotal[i] = gThrottleMaximumBPS[i];
00221 }
00222 }
00223 }
00224
00225
00226
00227
00228 void LLThrottleGroup::resetDynamicAdjust()
00229 {
00230 F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
00231 S32 i;
00232 for (i = 0; i < TC_EOF; i++)
00233 {
00234 mCurrentBPS[i] = mNominalBPS[i];
00235 mBitsAvailable[i] = mNominalBPS[i] * THROTTLE_LOOKAHEAD_TIME;
00236 mLastSendTime[i] = mt_sec;
00237 mBitsSentThisPeriod[i] = 0;
00238 mBitsSentHistory[i] = 0;
00239 }
00240 mDynamicAdjustTime = mt_sec;
00241 }
00242
00243
00244 BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
00245 {
00246 BOOL changed = FALSE;
00247 S32 i;
00248 for (i = 0; i < TC_EOF; i++)
00249 {
00250 if (mNominalBPS[i] != throttle_vec[i])
00251 {
00252 changed = TRUE;
00253 mNominalBPS[i] = throttle_vec[i];
00254 }
00255 }
00256
00257
00258
00259 if (changed)
00260 {
00261 resetDynamicAdjust();
00262 }
00263
00264 return changed;
00265 }
00266
00267
00268 BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
00269 {
00270 BOOL retval = TRUE;
00271
00272 F32 category_bps = mCurrentBPS[throttle_cat];
00273 F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
00274
00275
00276
00277 F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
00278 F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
00279
00280 if (bits_available >= lookahead_bits)
00281 {
00282
00283
00284 mBitsAvailable[throttle_cat] = lookahead_bits;
00285 retval = FALSE;
00286 }
00287 else if ( bits_available > bits )
00288 {
00289
00290 retval = FALSE;
00291 }
00292
00293 return retval;
00294 }
00295
00296 BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
00297 {
00298 F32 elapsed_time;
00299 F32 category_bps;
00300 F32 lookahead_bits;
00301 BOOL retval = TRUE;
00302
00303 category_bps = mCurrentBPS[throttle_cat];
00304 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
00305
00306 F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
00307 elapsed_time = (F32)(mt_sec - mLastSendTime[throttle_cat]);
00308 mLastSendTime[throttle_cat] = mt_sec;
00309 mBitsAvailable[throttle_cat] += category_bps * elapsed_time;
00310
00311 if (mBitsAvailable[throttle_cat] >= lookahead_bits)
00312 {
00313
00314
00315 mBitsAvailable[throttle_cat] = lookahead_bits;
00316 retval = FALSE;
00317 }
00318 else if ( mBitsAvailable[throttle_cat] > bits )
00319 {
00320
00321 retval = FALSE;
00322 }
00323
00324
00325 mBitsAvailable[throttle_cat] -= bits;
00326
00327 mBitsSentThisPeriod[throttle_cat] += bits;
00328
00329
00330
00331
00332
00333 return retval;
00334 }
00335
00336
00337 BOOL LLThrottleGroup::dynamicAdjust()
00338 {
00339 const F32 DYNAMIC_ADJUST_TIME = 1.0f;
00340 const F32 CURRENT_PERIOD_WEIGHT = .25f;
00341 const F32 BUSY_PERCENT = 0.75f;
00342 const F32 IDLE_PERCENT = 0.70f;
00343 const F32 TRANSFER_PERCENT = 0.90f;
00344 const F32 RECOVER_PERCENT = 0.25f;
00345
00346 S32 i;
00347
00348 F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
00349
00350
00351 if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME)
00352 {
00353 return FALSE;
00354 }
00355 mDynamicAdjustTime = mt_sec;
00356
00357 S32 total = 0;
00358
00359 for (i = 0; i < TC_EOF; i++)
00360 {
00361 if (mBitsSentHistory[i] == 0)
00362 {
00363
00364 mBitsSentHistory[i] = mBitsSentThisPeriod[i];
00365 }
00366 else
00367 {
00368
00369 mBitsSentHistory[i] = (1.f - CURRENT_PERIOD_WEIGHT) * mBitsSentHistory[i]
00370 + CURRENT_PERIOD_WEIGHT * mBitsSentThisPeriod[i];
00371 }
00372
00373 mBitsSentThisPeriod[i] = 0;
00374 total += llround(mBitsSentHistory[i]);
00375 }
00376
00377
00378
00379 BOOL channels_busy = FALSE;
00380 F32 busy_nominal_sum = 0;
00381 BOOL channel_busy[TC_EOF];
00382 BOOL channel_idle[TC_EOF];
00383 BOOL channel_over_nominal[TC_EOF];
00384
00385 for (i = 0; i < TC_EOF; i++)
00386 {
00387
00388 if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i])
00389 {
00390
00391 channels_busy = TRUE;
00392 busy_nominal_sum += mNominalBPS[i];
00393 channel_busy[i] = TRUE;
00394 }
00395 else
00396 {
00397 channel_busy[i] = FALSE;
00398 }
00399
00400
00401 if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i]) &&
00402 (mBitsAvailable[i] > 0))
00403 {
00404 channel_idle[i] = TRUE;
00405 }
00406 else
00407 {
00408 channel_idle[i] = FALSE;
00409 }
00410
00411
00412 if (mCurrentBPS[i] > mNominalBPS[i])
00413 {
00414 channel_over_nominal[i] = TRUE;
00415 }
00416 else
00417 {
00418 channel_over_nominal[i] = FALSE;
00419 }
00420
00421
00422
00423
00424
00425
00426 }
00427
00428 if (channels_busy)
00429 {
00430
00431 F32 used_bps;
00432 F32 avail_bps;
00433 F32 transfer_bps;
00434
00435 F32 pool_bps = 0;
00436
00437 for (i = 0; i < TC_EOF; i++)
00438 {
00439 if (channel_idle[i] || channel_over_nominal[i] )
00440 {
00441
00442
00443
00444
00445 used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME;
00446
00447
00448
00449
00450 if (used_bps < gThrottleMinimumBPS[i])
00451 {
00452 used_bps = gThrottleMinimumBPS[i];
00453 }
00454
00455 if (channel_over_nominal[i])
00456 {
00457 F32 unused_current = mCurrentBPS[i] - used_bps;
00458 avail_bps = llmax(mCurrentBPS[i] - mNominalBPS[i], unused_current);
00459 }
00460 else
00461 {
00462 avail_bps = mCurrentBPS[i] - used_bps;
00463 }
00464
00465
00466
00467
00468
00469
00470 if (avail_bps < 0)
00471 {
00472 continue;
00473 }
00474
00475
00476 transfer_bps = avail_bps * TRANSFER_PERCENT;
00477 mCurrentBPS[i] -= transfer_bps;
00478 pool_bps += transfer_bps;
00479 }
00480 }
00481
00482
00483
00484 F32 unused_bps = 0.f;
00485
00486 for (i = 0; i < TC_EOF; i++)
00487 {
00488 if (channel_busy[i])
00489 {
00490 F32 add_amount = pool_bps * (mNominalBPS[i] / busy_nominal_sum);
00491
00492 mCurrentBPS[i] += add_amount;
00493
00494
00495
00496
00497
00498
00499
00500 const F32 MAX_BPS = 4 * mNominalBPS[i];
00501 if (mCurrentBPS[i] > MAX_BPS)
00502 {
00503 F32 overage = mCurrentBPS[i] - MAX_BPS;
00504 mCurrentBPS[i] -= overage;
00505 unused_bps += overage;
00506 }
00507
00508
00509 if (mCurrentBPS[i] < gThrottleMinimumBPS[i])
00510 {
00511 mCurrentBPS[i] = gThrottleMinimumBPS[i];
00512 }
00513 }
00514 }
00515
00516
00517 if (unused_bps > 0.f)
00518 {
00519 mCurrentBPS[TC_TASK] += unused_bps;
00520 }
00521 }
00522 else
00523 {
00524
00525
00526
00527
00528 F32 starved_nominal_sum = 0;
00529 F32 avail_bps = 0;
00530 F32 transfer_bps = 0;
00531 F32 pool_bps = 0;
00532 for (i = 0; i < TC_EOF; i++)
00533 {
00534 if (mCurrentBPS[i] > mNominalBPS[i])
00535 {
00536 avail_bps = (mCurrentBPS[i] - mNominalBPS[i]);
00537 transfer_bps = avail_bps * RECOVER_PERCENT;
00538
00539 mCurrentBPS[i] -= transfer_bps;
00540 pool_bps += transfer_bps;
00541 }
00542 }
00543
00544
00545
00546 for (i = 0; i < TC_EOF; i++)
00547 {
00548 if (mCurrentBPS[i] < mNominalBPS[i])
00549 {
00550
00551 starved_nominal_sum += mNominalBPS[i];
00552 }
00553 }
00554
00555 for (i = 0; i < TC_EOF; i++)
00556 {
00557 if (mCurrentBPS[i] < mNominalBPS[i])
00558 {
00559
00560 mCurrentBPS[i] += pool_bps * (mNominalBPS[i] / starved_nominal_sum);
00561 }
00562 }
00563 }
00564 return TRUE;
00565 }