llthrottle.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llthrottle.cpp
  3.  * @brief LLThrottle class used for network bandwidth control.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llthrottle.h"
  34. #include "llmath.h"
  35. #include "lldatapacker.h"
  36. #include "message.h"
  37. LLThrottle::LLThrottle(const F32 rate)
  38. {
  39. mRate = rate;
  40. mAvailable = 0.f;
  41. mLookaheadSecs = 0.25f;
  42. mLastSendTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
  43. }
  44. void LLThrottle::setRate(const F32 rate)
  45. {
  46. // Need to accumulate available bits when adjusting the rate.
  47. mAvailable = getAvailable();
  48. mLastSendTime = LLMessageSystem::getMessageTimeSeconds();
  49. mRate = rate;
  50. }
  51. F32 LLThrottle::getAvailable()
  52. {
  53. // use a temporary bits_available
  54. // since we don't want to change mBitsAvailable every time
  55. F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
  56. return mAvailable + (mRate * elapsed_time);
  57. }
  58. BOOL LLThrottle::checkOverflow(const F32 amount)
  59. {
  60. BOOL retval = TRUE;
  61. F32 lookahead_amount = mRate * mLookaheadSecs;
  62. // use a temporary bits_available
  63. // since we don't want to change mBitsAvailable every time
  64. F32 elapsed_time =  (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
  65. F32 amount_available = mAvailable + (mRate * elapsed_time);
  66. if ((amount_available >= lookahead_amount) || (amount_available > amount))
  67. {
  68. // ...enough space to send this message
  69. // Also do if > lookahead so we can use if amount > capped amount.
  70. retval = FALSE;
  71. }
  72. return retval;
  73. }
  74. BOOL LLThrottle::throttleOverflow(const F32 amount)
  75. {
  76. F32 elapsed_time;
  77. F32 lookahead_amount;
  78. BOOL retval = TRUE;
  79. lookahead_amount = mRate * mLookaheadSecs;
  80. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
  81. elapsed_time = (F32)(mt_sec - mLastSendTime);
  82. mLastSendTime = mt_sec;
  83. mAvailable += mRate * elapsed_time;
  84. if (mAvailable >= lookahead_amount)
  85. {
  86. // ...channel completely open, so allow send regardless
  87. // of size.  This allows sends on very low BPS channels.
  88. mAvailable = lookahead_amount;
  89. retval = FALSE;
  90. }
  91. else if (mAvailable > amount)
  92. {
  93. // ...enough space to send this message
  94. retval = FALSE;
  95. }
  96. // We actually already sent the bits.
  97. mAvailable -= amount;
  98. // What if bitsavailable goes negative?
  99. // That's OK, because it means someone is banging on the channel,
  100. // so we need some time to recover.
  101. return retval;
  102. }
  103. const F32 THROTTLE_LOOKAHEAD_TIME = 1.f; // seconds
  104. // Make sure that we don't set above these
  105. // values, even if the client asks to be set
  106. // higher
  107. // Note that these values are replicated on the 
  108. // client side to set max bandwidth throttling there,
  109. // in llviewerthrottle.cpp. These values are the sum
  110. // of the top two tiers of bandwidth there.
  111. F32 gThrottleMaximumBPS[TC_EOF] =
  112. {
  113. 150000.f, // TC_RESEND
  114. 170000.f, // TC_LAND
  115. 34000.f, // TC_WIND
  116. 34000.f, // TC_CLOUD
  117. 446000.f, // TC_TASK
  118. 446000.f, // TC_TEXTURE
  119. 220000.f, // TC_ASSET
  120. };
  121. // Start low until viewer informs us of capability
  122. // Asset and resend get high values, since they
  123. // aren't used JUST by the viewer necessarily.
  124. // This is a HACK and should be dealt with more properly on
  125. // circuit creation.
  126. F32 gThrottleDefaultBPS[TC_EOF] =
  127. {
  128. 100000.f, // TC_RESEND
  129. 4000.f, // TC_LAND
  130. 4000.f, // TC_WIND
  131. 4000.f, // TC_CLOUD
  132. 4000.f, // TC_TASK
  133. 4000.f, // TC_TEXTURE
  134. 100000.f, // TC_ASSET
  135. };
  136. // Don't throttle down lower than this
  137. // This potentially wastes 50 kbps, but usually
  138. // wont.
  139. F32 gThrottleMinimumBPS[TC_EOF] =
  140. {
  141. 10000.f, // TC_RESEND
  142. 10000.f, // TC_LAND
  143.  4000.f, // TC_WIND
  144.  4000.f, // TC_CLOUD
  145. 20000.f, // TC_TASK
  146. 10000.f, // TC_TEXTURE
  147. 10000.f, // TC_ASSET
  148. };
  149. const char* THROTTLE_NAMES[TC_EOF] =
  150. {
  151. "Resend ",
  152. "Land   ",
  153. "Wind   ",
  154. "Cloud  ",
  155. "Task   ",
  156. "Texture",
  157. "Asset  "
  158. };
  159. LLThrottleGroup::LLThrottleGroup()
  160. {
  161. S32 i;
  162. for (i = 0; i < TC_EOF; i++)
  163. {
  164. mThrottleTotal[i] = gThrottleDefaultBPS[i];
  165. mNominalBPS[i] = gThrottleDefaultBPS[i];
  166. }
  167. resetDynamicAdjust();
  168. }
  169. void LLThrottleGroup::packThrottle(LLDataPacker &dp) const
  170. {
  171. S32 i;
  172. for (i = 0; i < TC_EOF; i++)
  173. {
  174. dp.packF32(mThrottleTotal[i], "Throttle");
  175. }
  176. }
  177. void LLThrottleGroup::unpackThrottle(LLDataPacker &dp)
  178. {
  179. S32 i;
  180. for (i = 0; i < TC_EOF; i++)
  181. {
  182. F32 temp_throttle;
  183. dp.unpackF32(temp_throttle, "Throttle");
  184. temp_throttle = llclamp(temp_throttle, 0.f, 2250000.f);
  185. mThrottleTotal[i] = temp_throttle;
  186. if(mThrottleTotal[i] > gThrottleMaximumBPS[i])
  187. {
  188. mThrottleTotal[i] = gThrottleMaximumBPS[i];
  189. }
  190. }
  191. }
  192. // Call this whenever mNominalBPS changes.  Need to reset
  193. // the measurement systems.  In the future, we should look
  194. // into NOT resetting the system.
  195. void LLThrottleGroup::resetDynamicAdjust()
  196. {
  197. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
  198. S32 i;
  199. for (i = 0; i < TC_EOF; i++)
  200. {
  201. mCurrentBPS[i] = mNominalBPS[i];
  202. mBitsAvailable[i] = mNominalBPS[i] * THROTTLE_LOOKAHEAD_TIME;
  203. mLastSendTime[i] = mt_sec;
  204. mBitsSentThisPeriod[i] = 0;
  205. mBitsSentHistory[i] = 0;
  206. }
  207. mDynamicAdjustTime = mt_sec;
  208. }
  209. BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
  210. {
  211. BOOL changed = FALSE;
  212. S32 i;
  213. for (i = 0; i < TC_EOF; i++)
  214. {
  215. if (mNominalBPS[i] != throttle_vec[i])
  216. {
  217. changed = TRUE;
  218. mNominalBPS[i] = throttle_vec[i];
  219. }
  220. }
  221. // If we changed the nominal settings, reset the dynamic
  222. // adjustment subsystem.
  223. if (changed)
  224. {
  225. resetDynamicAdjust();
  226. }
  227. return changed;
  228. }
  229. // Return bits available in the channel
  230. S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
  231. {
  232. S32 retval = 0;
  233. F32 category_bps = mCurrentBPS[throttle_cat];
  234. F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
  235. // use a temporary bits_available
  236. // since we don't want to change mBitsAvailable every time
  237. F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
  238. F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
  239. if (bits_available >= lookahead_bits)
  240. {
  241. retval = (S32) gThrottleMaximumBPS[throttle_cat];
  242. }
  243. else 
  244. {
  245. retval = (S32) bits_available;
  246. }
  247. return retval;
  248. }
  249. BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
  250. {
  251. BOOL retval = TRUE;
  252. F32 category_bps = mCurrentBPS[throttle_cat];
  253. F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
  254. // use a temporary bits_available
  255. // since we don't want to change mBitsAvailable every time
  256. F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
  257. F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
  258. if (bits_available >= lookahead_bits)
  259. {
  260. // ...channel completely open, so allow send regardless
  261. // of size.  This allows sends on very low BPS channels.
  262. mBitsAvailable[throttle_cat] = lookahead_bits;
  263. retval = FALSE;
  264. }
  265. else if ( bits_available > bits )
  266. {
  267. // ...enough space to send this message
  268. retval = FALSE;
  269. }
  270. return retval;
  271. }
  272. BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
  273. {
  274. F32 elapsed_time;
  275. F32 category_bps;
  276. F32 lookahead_bits;
  277. BOOL retval = TRUE;
  278. category_bps = mCurrentBPS[throttle_cat];
  279. lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
  280. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
  281. elapsed_time = (F32)(mt_sec - mLastSendTime[throttle_cat]);
  282. mLastSendTime[throttle_cat] = mt_sec;
  283. mBitsAvailable[throttle_cat] += category_bps * elapsed_time;
  284. if (mBitsAvailable[throttle_cat] >= lookahead_bits)
  285. {
  286. // ...channel completely open, so allow send regardless
  287. // of size.  This allows sends on very low BPS channels.
  288. mBitsAvailable[throttle_cat] = lookahead_bits;
  289. retval = FALSE;
  290. }
  291. else if ( mBitsAvailable[throttle_cat] > bits )
  292. {
  293. // ...enough space to send this message
  294. retval = FALSE;
  295. }
  296. // We actually already sent the bits.
  297. mBitsAvailable[throttle_cat] -= bits;
  298. mBitsSentThisPeriod[throttle_cat] += bits;
  299. // What if bitsavailable goes negative?
  300. // That's OK, because it means someone is banging on the channel,
  301. // so we need some time to recover.
  302. return retval;
  303. }
  304. BOOL LLThrottleGroup::dynamicAdjust()
  305. {
  306. const F32 DYNAMIC_ADJUST_TIME = 1.0f; // seconds
  307. const F32 CURRENT_PERIOD_WEIGHT = .25f; // how much weight to give to last period while determining BPS utilization
  308. const F32 BUSY_PERCENT = 0.75f; // if use more than this fraction of BPS, you are busy
  309. const F32 IDLE_PERCENT = 0.70f; // if use less than this fraction, you are "idle"
  310. const F32 TRANSFER_PERCENT = 0.90f; // how much unused bandwidth to take away each adjustment
  311. const F32 RECOVER_PERCENT = 0.25f; // how much to give back during recovery phase
  312. S32 i;
  313. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
  314. // Only dynamically adjust every few seconds
  315. if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME)
  316. {
  317. return FALSE;
  318. }
  319. mDynamicAdjustTime = mt_sec;
  320. S32 total = 0;
  321. // Update historical information
  322. for (i = 0; i < TC_EOF; i++)
  323. {
  324. if (mBitsSentHistory[i] == 0)
  325. {
  326. // first run, just copy current period
  327. mBitsSentHistory[i] = mBitsSentThisPeriod[i];
  328. }
  329. else
  330. {
  331. // have some history, so weight accordingly
  332. mBitsSentHistory[i] = (1.f - CURRENT_PERIOD_WEIGHT) * mBitsSentHistory[i] 
  333. + CURRENT_PERIOD_WEIGHT * mBitsSentThisPeriod[i];
  334. }
  335. mBitsSentThisPeriod[i] = 0;
  336. total += llround(mBitsSentHistory[i]);
  337. }
  338. // Look for busy channels
  339. // TODO: Fold into loop above.
  340. BOOL channels_busy = FALSE;
  341. F32  busy_nominal_sum = 0;
  342. BOOL channel_busy[TC_EOF];
  343. BOOL channel_idle[TC_EOF];
  344. BOOL channel_over_nominal[TC_EOF];
  345. for (i = 0; i < TC_EOF; i++)
  346. {
  347. // Is this a busy channel?
  348. if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i])
  349. {
  350. // this channel is busy
  351. channels_busy = TRUE;
  352. busy_nominal_sum += mNominalBPS[i]; // use for allocation of pooled idle bandwidth
  353. channel_busy[i] = TRUE;
  354. }
  355. else
  356. {
  357. channel_busy[i] = FALSE;
  358. }
  359. // Is this an idle channel?
  360. if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i]) &&
  361. (mBitsAvailable[i] > 0))
  362. {
  363. channel_idle[i] = TRUE;
  364. }
  365. else
  366. {
  367. channel_idle[i] = FALSE;
  368. }
  369. // Is this an overpumped channel?
  370. if (mCurrentBPS[i] > mNominalBPS[i])
  371. {
  372. channel_over_nominal[i] = TRUE;
  373. }
  374. else
  375. {
  376. channel_over_nominal[i] = FALSE;
  377. }
  378. //if (total)
  379. //{
  380. // llinfos << i << ": B" << channel_busy[i] << " I" << channel_idle[i] << " N" << channel_over_nominal[i];
  381. // llcont << " Nom: " << mNominalBPS[i] << " Cur: " << mCurrentBPS[i] << " BS: " << mBitsSentHistory[i] << llendl;
  382. //}
  383. }
  384. if (channels_busy)
  385. {
  386. // Some channels are busy.  Let's see if we can get them some bandwidth.
  387. F32 used_bps;
  388. F32 avail_bps;
  389. F32 transfer_bps;
  390. F32 pool_bps = 0;
  391. for (i = 0; i < TC_EOF; i++)
  392. {
  393. if (channel_idle[i] || channel_over_nominal[i] )
  394. {
  395. // Either channel i is idle, or has been overpumped.
  396. // Therefore it's a candidate to give up some bandwidth.
  397. // Figure out how much bandwidth it has been using, and how
  398. // much is available to steal.
  399. used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME;
  400. // CRO make sure to keep a minimum amount of throttle available
  401. // CRO NB: channels set to < MINIMUM_BPS will never give up bps, 
  402. // which is correct I think
  403. if (used_bps < gThrottleMinimumBPS[i])
  404. {
  405. used_bps = gThrottleMinimumBPS[i];
  406. }
  407. if (channel_over_nominal[i])
  408. {
  409. F32 unused_current = mCurrentBPS[i] - used_bps;
  410. avail_bps = llmax(mCurrentBPS[i] - mNominalBPS[i], unused_current);
  411. }
  412. else
  413. {
  414. avail_bps = mCurrentBPS[i] - used_bps;
  415. }
  416. //llinfos << i << " avail " << avail_bps << llendl;
  417. // Historically, a channel could have used more than its current share,
  418. // even if it's idle right now.
  419. // Make sure we don't steal too much.
  420. if (avail_bps < 0)
  421. {
  422. continue;
  423. }
  424. // Transfer some bandwidth from this channel into the global pool.
  425. transfer_bps = avail_bps * TRANSFER_PERCENT;
  426. mCurrentBPS[i] -= transfer_bps;
  427. pool_bps += transfer_bps;
  428. }
  429. }
  430. //llinfos << "Pool BPS: " << pool_bps << llendl;
  431. // Now redistribute the bandwidth to busy channels.
  432. F32 unused_bps = 0.f;
  433. for (i = 0; i < TC_EOF; i++)
  434. {
  435. if (channel_busy[i])
  436. {
  437. F32 add_amount = pool_bps * (mNominalBPS[i] / busy_nominal_sum);
  438. //llinfos << "Busy " << i << " gets " << pool_bps << llendl;
  439. mCurrentBPS[i] += add_amount;
  440. // CRO: make sure this doesn't get too huge
  441. // JC - Actually, need to let mCurrentBPS go less than nominal, otherwise
  442. // you aren't allowing bandwidth to actually be moved from one channel
  443. // to another.  
  444. // *TODO: If clamping high end, would be good to re-
  445. // allocate to other channels in the above code.
  446. const F32 MAX_BPS = 4 * mNominalBPS[i];
  447. if (mCurrentBPS[i] > MAX_BPS)
  448. {
  449. F32 overage = mCurrentBPS[i] - MAX_BPS;
  450. mCurrentBPS[i] -= overage;
  451. unused_bps += overage;
  452. }
  453. // Paranoia
  454. if (mCurrentBPS[i] < gThrottleMinimumBPS[i])
  455. {
  456. mCurrentBPS[i] = gThrottleMinimumBPS[i];
  457. }
  458. }
  459. }
  460. // For fun, add the overage back in to objects
  461. if (unused_bps > 0.f)
  462. {
  463. mCurrentBPS[TC_TASK] += unused_bps;
  464. }
  465. }
  466. else
  467. {
  468. // No one is busy.
  469. // Make the channel allocations seek toward nominal.
  470. // Look for overpumped channels
  471. F32 starved_nominal_sum = 0;
  472. F32 avail_bps = 0;
  473. F32 transfer_bps = 0;
  474. F32 pool_bps = 0;
  475. for (i = 0; i < TC_EOF; i++)
  476. {
  477. if (mCurrentBPS[i] > mNominalBPS[i])
  478. {
  479. avail_bps = (mCurrentBPS[i] - mNominalBPS[i]);
  480. transfer_bps = avail_bps * RECOVER_PERCENT;
  481. mCurrentBPS[i] -= transfer_bps;
  482. pool_bps += transfer_bps;
  483. }
  484. }
  485. // Evenly distribute bandwidth to channels currently
  486. // using less than nominal.
  487. for (i = 0; i < TC_EOF; i++)
  488. {
  489. if (mCurrentBPS[i] < mNominalBPS[i])
  490. {
  491. // We're going to weight allocations by nominal BPS.
  492. starved_nominal_sum += mNominalBPS[i];
  493. }
  494. }
  495. for (i = 0; i < TC_EOF; i++)
  496. {
  497. if (mCurrentBPS[i] < mNominalBPS[i])
  498. {
  499. // Distribute bandwidth according to nominal allocation ratios.
  500. mCurrentBPS[i] += pool_bps * (mNominalBPS[i] / starved_nominal_sum);
  501. }
  502. }
  503. }
  504. return TRUE;
  505. }