aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerthrottle.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerthrottle.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llviewerthrottle.cpp')
-rw-r--r--linden/indra/newview/llviewerthrottle.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewerthrottle.cpp b/linden/indra/newview/llviewerthrottle.cpp
new file mode 100644
index 0000000..7f09937
--- /dev/null
+++ b/linden/indra/newview/llviewerthrottle.cpp
@@ -0,0 +1,332 @@
1/**
2 * @file llviewerthrottle.cpp
3 * @brief LLViewerThrottle class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29#include "llviewerthrottle.h"
30
31#include "llviewercontrol.h"
32#include "message.h"
33#include "llagent.h"
34#include "llframetimer.h"
35#include "llviewerstats.h"
36#include "lldatapacker.h"
37
38// consts
39
40// The viewer is allowed to set the under-the-hood bandwidth to 50%
41// greater than the prefs UI shows, under the assumption that the
42// viewer won't receive all the different message types at once.
43// I didn't design this, don't know who did. JC
44const F32 MAX_FRACTIONAL = 1.5f;
45const F32 MIN_FRACTIONAL = 0.2f;
46
47const F32 MIN_BANDWIDTH = 50.f;
48const F32 MAX_BANDWIDTH = 1500.f;
49const F32 STEP_FRACTIONAL = 0.1f;
50const F32 TIGHTEN_THROTTLE_THRESHOLD = 3.0f; // packet loss % per s
51const F32 EASE_THROTTLE_THRESHOLD = 0.5f; // packet loss % per s
52const F32 DYNAMIC_UPDATE_DURATION = 5.0f; // seconds
53
54LLViewerThrottle gViewerThrottle;
55
56// static
57const char *LLViewerThrottle::sNames[TC_EOF] = {
58 "Resend",
59 "Land",
60 "Wind",
61 "Cloud",
62 "Task",
63 "Texture",
64 "Asset"
65 };
66
67
68// Bandwidth settings for different bit rates, they're interpolated/extrapolated.
69// Resend Land Wind Cloud Task Texture Asset
70const F32 BW_PRESET_50[TC_EOF] = { 5, 10, 3, 3, 10, 10, 9 };
71const F32 BW_PRESET_300[TC_EOF] = { 30, 40, 9, 9, 86, 86, 40 };
72const F32 BW_PRESET_500[TC_EOF] = { 50, 70, 14, 14, 136, 136, 80 };
73const F32 BW_PRESET_1000[TC_EOF] = { 100, 100, 20, 20, 310, 310, 140 };
74
75LLViewerThrottleGroup::LLViewerThrottleGroup()
76{
77 S32 i;
78 for (i = 0; i < TC_EOF; i++)
79 {
80 mThrottles[i] = 0.f;
81 }
82 mThrottleTotal = 0.f;
83}
84
85
86LLViewerThrottleGroup::LLViewerThrottleGroup(const F32 settings[])
87{
88 mThrottleTotal = 0.f;
89 S32 i;
90 for (i = 0; i < TC_EOF; i++)
91 {
92 mThrottles[i] = settings[i];
93 mThrottleTotal += settings[i];
94 }
95}
96
97
98LLViewerThrottleGroup LLViewerThrottleGroup::operator*(const F32 frac) const
99{
100 LLViewerThrottleGroup res;
101 res.mThrottleTotal = 0.f;
102
103 S32 i;
104 for (i = 0; i < TC_EOF; i++)
105 {
106 res.mThrottles[i] = mThrottles[i] * frac;
107 res.mThrottleTotal += res.mThrottles[i];
108 }
109
110 return res;
111}
112
113
114LLViewerThrottleGroup LLViewerThrottleGroup::operator+(const LLViewerThrottleGroup &b) const
115{
116 LLViewerThrottleGroup res;
117 res.mThrottleTotal = 0.f;
118
119 S32 i;
120 for (i = 0; i < TC_EOF; i++)
121 {
122 res.mThrottles[i] = mThrottles[i] + b.mThrottles[i];
123 res.mThrottleTotal += res.mThrottles[i];
124 }
125
126 return res;
127}
128
129
130LLViewerThrottleGroup LLViewerThrottleGroup::operator-(const LLViewerThrottleGroup &b) const
131{
132 LLViewerThrottleGroup res;
133 res.mThrottleTotal = 0.f;
134
135 S32 i;
136 for (i = 0; i < TC_EOF; i++)
137 {
138 res.mThrottles[i] = mThrottles[i] - b.mThrottles[i];
139 res.mThrottleTotal += res.mThrottles[i];
140 }
141
142 return res;
143}
144
145
146void LLViewerThrottleGroup::sendToSim() const
147{
148 llinfos << "Sending throttle settings, total BW " << mThrottleTotal << llendl;
149 LLMessageSystem* msg = gMessageSystem;
150
151 msg->newMessageFast(_PREHASH_AgentThrottle);
152 msg->nextBlockFast(_PREHASH_AgentData);
153 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
154 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
155 msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
156
157 msg->nextBlockFast(_PREHASH_Throttle);
158 msg->addU32Fast(_PREHASH_GenCounter, 0);
159
160 // Pack up the throttle data
161 U8 tmp[64];
162 LLDataPackerBinaryBuffer dp(tmp, MAX_THROTTLE_SIZE);
163 S32 i;
164 for (i = 0; i < TC_EOF; i++)
165 {
166 //sim wants BPS, not KBPS
167 dp.packF32(mThrottles[i] * 1024.0f, "Throttle");
168 }
169 S32 len = dp.getCurrentSize();
170 msg->addBinaryDataFast(_PREHASH_Throttles, tmp, len);
171
172 gAgent.sendReliableMessage();
173}
174
175
176void LLViewerThrottleGroup::dump()
177{
178 S32 i;
179 for (i = 0; i < TC_EOF; i++)
180 {
181 llinfos << LLViewerThrottle::sNames[i] << ": " << mThrottles[i] << llendl;
182 }
183 llinfos << "Total: " << mThrottleTotal << llendl;
184}
185
186class LLBPSListener : public LLSimpleListener
187{
188public:
189 virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
190 {
191 gViewerThrottle.setMaxBandwidth((F32) event->getValue().asReal()*1024);
192 return true;
193 }
194};
195
196LLViewerThrottle::LLViewerThrottle() :
197 mMaxBandwidth(0.f),
198 mCurrentBandwidth(0.f),
199 mThrottleFrac(1.f)
200{
201 // Need to be pushed on in bandwidth order
202 mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_50));
203 mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_300));
204 mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_500));
205 mPresets.push_back(LLViewerThrottleGroup(BW_PRESET_1000));
206}
207
208
209void LLViewerThrottle::setMaxBandwidth(F32 kbits_per_second, BOOL from_event)
210{
211 if (!from_event)
212 {
213 gSavedSettings.setF32("ThrottleBandwidthKBPS", kbits_per_second);
214 }
215 gViewerThrottle.load();
216
217 if (gAgent.getRegion())
218 {
219 gViewerThrottle.sendToSim();
220 }
221}
222
223void LLViewerThrottle::load()
224{
225 mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS")*1024;
226 resetDynamicThrottle();
227 mCurrent.dump();
228}
229
230
231void LLViewerThrottle::save() const
232{
233 gSavedSettings.setF32("ThrottleBandwidthKBPS", mMaxBandwidth/1024);
234}
235
236
237void LLViewerThrottle::sendToSim() const
238{
239 mCurrent.sendToSim();
240}
241
242
243LLViewerThrottleGroup LLViewerThrottle::getThrottleGroup(const F32 bandwidth_kbps)
244{
245 //Clamp the bandwidth users can set.
246 F32 set_bandwidth = llclamp(bandwidth_kbps, MIN_BANDWIDTH, MAX_BANDWIDTH);
247
248 S32 count = mPresets.size();
249
250 S32 i;
251 for (i = 0; i < count; i++)
252 {
253 if (mPresets[i].getTotal() > set_bandwidth)
254 {
255 break;
256 }
257 }
258
259 if (i == 0)
260 {
261 // We return the minimum if it's less than the minimum
262 return mPresets[0];
263 }
264 else if (i == count)
265 {
266 // Higher than the highest preset, we extrapolate out based on the
267 // last two presets. This allows us to keep certain throttle channels from
268 // growing in bandwidth
269 F32 delta_bw = set_bandwidth - mPresets[count-1].getTotal();
270 LLViewerThrottleGroup delta_throttle = mPresets[count - 1] - mPresets[count - 2];
271 F32 delta_total = delta_throttle.getTotal();
272 F32 delta_frac = delta_bw / delta_total;
273 delta_throttle = delta_throttle * delta_frac;
274 return mPresets[count-1] + delta_throttle;
275 }
276 else
277 {
278 // In between two presets, just interpolate
279 F32 delta_bw = set_bandwidth - mPresets[i - 1].getTotal();
280 LLViewerThrottleGroup delta_throttle = mPresets[i] - mPresets[i - 1];
281 F32 delta_total = delta_throttle.getTotal();
282 F32 delta_frac = delta_bw / delta_total;
283 delta_throttle = delta_throttle * delta_frac;
284 return mPresets[i - 1] + delta_throttle;
285 }
286}
287
288
289// static
290void LLViewerThrottle::resetDynamicThrottle()
291{
292 mThrottleFrac = MAX_FRACTIONAL;
293
294 mCurrentBandwidth = mMaxBandwidth*MAX_FRACTIONAL;
295 mCurrent = getThrottleGroup(mCurrentBandwidth / 1024.0f);
296}
297
298void LLViewerThrottle::updateDynamicThrottle()
299{
300 if (mUpdateTimer.getElapsedTimeF32() < DYNAMIC_UPDATE_DURATION)
301 {
302 return;
303 }
304 mUpdateTimer.reset();
305
306 if (gViewerStats->mPacketsLostPercentStat.getMean() > TIGHTEN_THROTTLE_THRESHOLD)
307 {
308 if (mThrottleFrac <= MIN_FRACTIONAL || mCurrentBandwidth / 1024.0f <= MIN_BANDWIDTH)
309 {
310 return;
311 }
312 mThrottleFrac -= STEP_FRACTIONAL;
313 mThrottleFrac = llmax(MIN_FRACTIONAL, mThrottleFrac);
314 mCurrentBandwidth = mMaxBandwidth * mThrottleFrac;
315 mCurrent = getThrottleGroup(mCurrentBandwidth / 1024.0f);
316 mCurrent.sendToSim();
317 llinfos << "Tightening network throttle to " << mCurrentBandwidth << llendl;
318 }
319 else if (gViewerStats->mPacketsLostPercentStat.getMean() <= EASE_THROTTLE_THRESHOLD)
320 {
321 if (mThrottleFrac >= MAX_FRACTIONAL || mCurrentBandwidth / 1024.0f >= MAX_BANDWIDTH)
322 {
323 return;
324 }
325 mThrottleFrac += STEP_FRACTIONAL;
326 mThrottleFrac = llmin(MAX_FRACTIONAL, mThrottleFrac);
327 mCurrentBandwidth = mMaxBandwidth * mThrottleFrac;
328 mCurrent = getThrottleGroup(mCurrentBandwidth/1024.0f);
329 mCurrent.sendToSim();
330 llinfos << "Easing network throttle to " << mCurrentBandwidth << llendl;
331 }
332}