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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewerthrottle.cpp
  3.  * @brief LLViewerThrottle class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-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 "llviewerprecompiledheaders.h"
  33. #include "llviewerthrottle.h"
  34. #include "llviewercontrol.h"
  35. #include "message.h"
  36. #include "llagent.h"
  37. #include "llframetimer.h"
  38. #include "llviewerstats.h"
  39. #include "lldatapacker.h"
  40. using namespace LLOldEvents;
  41. // consts
  42. // The viewer is allowed to set the under-the-hood bandwidth to 50%
  43. // greater than the prefs UI shows, under the assumption that the
  44. // viewer won't receive all the different message types at once.
  45. // I didn't design this, don't know who did. JC
  46. const F32 MAX_FRACTIONAL = 1.5f;
  47. const F32 MIN_FRACTIONAL = 0.2f;
  48. const F32 MIN_BANDWIDTH = 50.f;
  49. const F32 MAX_BANDWIDTH = 1500.f;
  50. const F32 STEP_FRACTIONAL = 0.1f;
  51. const F32 TIGHTEN_THROTTLE_THRESHOLD = 3.0f; // packet loss % per s
  52. const F32 EASE_THROTTLE_THRESHOLD = 0.5f; // packet loss % per s
  53. const F32 DYNAMIC_UPDATE_DURATION = 5.0f; // seconds
  54. LLViewerThrottle gViewerThrottle;
  55. // static
  56. const std:: string LLViewerThrottle::sNames[TC_EOF] = {
  57. "Resend",
  58. "Land",
  59. "Wind",
  60. "Cloud",
  61. "Task",
  62. "Texture",
  63. "Asset"
  64. };
  65. // Bandwidth settings for different bit rates, they're interpolated/extrapolated.
  66. //                                Resend Land Wind Cloud Task Texture Asset
  67. const F32 BW_PRESET_50[TC_EOF]   = {   5,  10,   3,   3,  10,  10,   9 };
  68. const F32 BW_PRESET_300[TC_EOF]  = {  30,  40,   9,   9,  86,  86,  40 };
  69. const F32 BW_PRESET_500[TC_EOF]  = {  50,  70,  14,  14, 136, 136,  80 };
  70. const F32 BW_PRESET_1000[TC_EOF] = { 100, 100,  20,  20, 310, 310, 140 };
  71. LLViewerThrottleGroup::LLViewerThrottleGroup()
  72. {
  73. S32 i;
  74. for (i = 0; i < TC_EOF; i++)
  75. {
  76. mThrottles[i] = 0.f;
  77. }
  78. mThrottleTotal = 0.f;
  79. }
  80. LLViewerThrottleGroup::LLViewerThrottleGroup(const F32 settings[])
  81. {
  82. mThrottleTotal = 0.f;
  83. S32 i;
  84. for (i = 0; i < TC_EOF; i++)
  85. {
  86. mThrottles[i] = settings[i];
  87. mThrottleTotal += settings[i];
  88. }
  89. }
  90. LLViewerThrottleGroup LLViewerThrottleGroup::operator*(const F32 frac) const
  91. {
  92. LLViewerThrottleGroup res;
  93. res.mThrottleTotal = 0.f;
  94. S32 i;
  95. for (i = 0; i < TC_EOF; i++)
  96. {
  97. res.mThrottles[i] = mThrottles[i] * frac;
  98. res.mThrottleTotal += res.mThrottles[i];
  99. }
  100. return res;
  101. }
  102. LLViewerThrottleGroup LLViewerThrottleGroup::operator+(const LLViewerThrottleGroup &b) const
  103. {
  104. LLViewerThrottleGroup res;
  105. res.mThrottleTotal = 0.f;
  106. S32 i;
  107. for (i = 0; i < TC_EOF; i++)
  108. {
  109. res.mThrottles[i] = mThrottles[i] + b.mThrottles[i];
  110. res.mThrottleTotal += res.mThrottles[i];
  111. }
  112. return res;
  113. }
  114. LLViewerThrottleGroup LLViewerThrottleGroup::operator-(const LLViewerThrottleGroup &b) const
  115. {
  116. LLViewerThrottleGroup res;
  117. res.mThrottleTotal = 0.f;
  118. S32 i;
  119. for (i = 0; i < TC_EOF; i++)
  120. {
  121. res.mThrottles[i] = mThrottles[i] - b.mThrottles[i];
  122. res.mThrottleTotal += res.mThrottles[i];
  123. }
  124. return res;
  125. }
  126. void LLViewerThrottleGroup::sendToSim() const
  127. {
  128. llinfos << "Sending throttle settings, total BW " << mThrottleTotal << llendl;
  129. LLMessageSystem* msg = gMessageSystem;
  130. msg->newMessageFast(_PREHASH_AgentThrottle);
  131. msg->nextBlockFast(_PREHASH_AgentData);
  132. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  133. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  134. msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
  135. msg->nextBlockFast(_PREHASH_Throttle);
  136. msg->addU32Fast(_PREHASH_GenCounter, 0);
  137. // Pack up the throttle data
  138. U8 tmp[64];
  139. LLDataPackerBinaryBuffer dp(tmp, MAX_THROTTLE_SIZE);
  140. S32 i;
  141. for (i = 0; i < TC_EOF; i++)
  142. {
  143. //sim wants BPS, not KBPS
  144. dp.packF32(mThrottles[i] * 1024.0f, "Throttle");
  145. }
  146. S32 len = dp.getCurrentSize();
  147. msg->addBinaryDataFast(_PREHASH_Throttles, tmp, len);
  148. gAgent.sendReliableMessage();
  149. }
  150. void LLViewerThrottleGroup::dump()
  151. {
  152. S32 i;
  153. for (i = 0; i < TC_EOF; i++)
  154. {
  155. LL_DEBUGS("Throttle") << LLViewerThrottle::sNames[i] << ": " << mThrottles[i] << LL_ENDL;
  156. }
  157. LL_DEBUGS("Throttle") << "Total: " << mThrottleTotal << LL_ENDL;
  158. }
  159. class LLBPSListener : public LLSimpleListener
  160. {
  161. public:
  162. virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
  163. {
  164. gViewerThrottle.setMaxBandwidth((F32) event->getValue().asReal()*1024);
  165. return true;
  166. }
  167. };
  168. LLViewerThrottle::LLViewerThrottle() :
  169. mMaxBandwidth(0.f),
  170. mCurrentBandwidth(0.f),
  171. mThrottleFrac(1.f)
  172. {
  173. // Need to be pushed on in bandwidth order
  174. mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_50));
  175. mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_300));
  176. mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_500));
  177. mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_1000));
  178. }
  179. void LLViewerThrottle::setMaxBandwidth(F32 kbits_per_second, BOOL from_event)
  180. {
  181. if (!from_event)
  182. {
  183. gSavedSettings.setF32("ThrottleBandwidthKBPS", kbits_per_second);
  184. }
  185. gViewerThrottle.load();
  186. if (gAgent.getRegion())
  187. {
  188. gViewerThrottle.sendToSim();
  189. }
  190. }
  191. void LLViewerThrottle::load()
  192. {
  193. mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS")*1024;
  194. resetDynamicThrottle();
  195. mCurrent.dump();
  196. }
  197. void LLViewerThrottle::save() const
  198. {
  199. gSavedSettings.setF32("ThrottleBandwidthKBPS", mMaxBandwidth/1024);
  200. }
  201. void LLViewerThrottle::sendToSim() const
  202. {
  203. mCurrent.sendToSim();
  204. }
  205. LLViewerThrottleGroup LLViewerThrottle::getThrottleGroup(const F32 bandwidth_kbps)
  206. {
  207. //Clamp the bandwidth users can set.
  208. F32 set_bandwidth = llclamp(bandwidth_kbps, MIN_BANDWIDTH, MAX_BANDWIDTH);
  209. S32 count = mPresets.size();
  210. S32 i;
  211. for (i = 0; i < count; i++)
  212. {
  213. if (mPresets[i].getTotal() > set_bandwidth)
  214. {
  215. break;
  216. }
  217. }
  218. if (i == 0)
  219. {
  220. // We return the minimum if it's less than the minimum
  221. return mPresets[0];
  222. }
  223. else if (i == count)
  224. {
  225. // Higher than the highest preset, we extrapolate out based on the
  226. // last two presets.  This allows us to keep certain throttle channels from
  227. // growing in bandwidth
  228. F32 delta_bw = set_bandwidth - mPresets[count-1].getTotal();
  229. LLViewerThrottleGroup delta_throttle = mPresets[count - 1] - mPresets[count - 2];
  230. F32 delta_total = delta_throttle.getTotal();
  231. F32 delta_frac = delta_bw / delta_total;
  232. delta_throttle = delta_throttle * delta_frac;
  233. return mPresets[count-1] + delta_throttle;
  234. }
  235. else
  236. {
  237. // In between two presets, just interpolate
  238. F32 delta_bw = set_bandwidth - mPresets[i - 1].getTotal();
  239. LLViewerThrottleGroup delta_throttle = mPresets[i] - mPresets[i - 1];
  240. F32 delta_total = delta_throttle.getTotal();
  241. F32 delta_frac = delta_bw / delta_total;
  242. delta_throttle = delta_throttle * delta_frac;
  243. return mPresets[i - 1] + delta_throttle;
  244. }
  245. }
  246. // static
  247. void LLViewerThrottle::resetDynamicThrottle()
  248. {
  249. mThrottleFrac = MAX_FRACTIONAL;
  250. mCurrentBandwidth = mMaxBandwidth*MAX_FRACTIONAL;
  251. mCurrent = getThrottleGroup(mCurrentBandwidth / 1024.0f);
  252. }
  253. void LLViewerThrottle::updateDynamicThrottle()
  254. {
  255. if (mUpdateTimer.getElapsedTimeF32() < DYNAMIC_UPDATE_DURATION)
  256. {
  257. return;
  258. }
  259. mUpdateTimer.reset();
  260. if (LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean() > TIGHTEN_THROTTLE_THRESHOLD)
  261. {
  262. if (mThrottleFrac <= MIN_FRACTIONAL || mCurrentBandwidth / 1024.0f <= MIN_BANDWIDTH)
  263. {
  264. return;
  265. }
  266. mThrottleFrac -= STEP_FRACTIONAL;
  267. mThrottleFrac = llmax(MIN_FRACTIONAL, mThrottleFrac);
  268. mCurrentBandwidth = mMaxBandwidth * mThrottleFrac;
  269. mCurrent = getThrottleGroup(mCurrentBandwidth / 1024.0f);
  270. mCurrent.sendToSim();
  271. llinfos << "Tightening network throttle to " << mCurrentBandwidth << llendl;
  272. }
  273. else if (LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean() <= EASE_THROTTLE_THRESHOLD)
  274. {
  275. if (mThrottleFrac >= MAX_FRACTIONAL || mCurrentBandwidth / 1024.0f >= MAX_BANDWIDTH)
  276. {
  277. return;
  278. }
  279. mThrottleFrac += STEP_FRACTIONAL;
  280. mThrottleFrac = llmin(MAX_FRACTIONAL, mThrottleFrac);
  281. mCurrentBandwidth = mMaxBandwidth * mThrottleFrac;
  282. mCurrent = getThrottleGroup(mCurrentBandwidth/1024.0f);
  283. mCurrent.sendToSim();
  284. llinfos << "Easing network throttle to " << mCurrentBandwidth << llendl;
  285. }
  286. }