diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerthrottle.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 332 |
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 | ||
44 | const F32 MAX_FRACTIONAL = 1.5f; | ||
45 | const F32 MIN_FRACTIONAL = 0.2f; | ||
46 | |||
47 | const F32 MIN_BANDWIDTH = 50.f; | ||
48 | const F32 MAX_BANDWIDTH = 1500.f; | ||
49 | const F32 STEP_FRACTIONAL = 0.1f; | ||
50 | const F32 TIGHTEN_THROTTLE_THRESHOLD = 3.0f; // packet loss % per s | ||
51 | const F32 EASE_THROTTLE_THRESHOLD = 0.5f; // packet loss % per s | ||
52 | const F32 DYNAMIC_UPDATE_DURATION = 5.0f; // seconds | ||
53 | |||
54 | LLViewerThrottle gViewerThrottle; | ||
55 | |||
56 | // static | ||
57 | const 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 | ||
70 | const F32 BW_PRESET_50[TC_EOF] = { 5, 10, 3, 3, 10, 10, 9 }; | ||
71 | const F32 BW_PRESET_300[TC_EOF] = { 30, 40, 9, 9, 86, 86, 40 }; | ||
72 | const F32 BW_PRESET_500[TC_EOF] = { 50, 70, 14, 14, 136, 136, 80 }; | ||
73 | const F32 BW_PRESET_1000[TC_EOF] = { 100, 100, 20, 20, 310, 310, 140 }; | ||
74 | |||
75 | LLViewerThrottleGroup::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 | |||
86 | LLViewerThrottleGroup::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 | |||
98 | LLViewerThrottleGroup 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 | |||
114 | LLViewerThrottleGroup 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 | |||
130 | LLViewerThrottleGroup 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 | |||
146 | void 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 | |||
176 | void 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 | |||
186 | class LLBPSListener : public LLSimpleListener | ||
187 | { | ||
188 | public: | ||
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 | |||
196 | LLViewerThrottle::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 | |||
209 | void 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 | |||
223 | void LLViewerThrottle::load() | ||
224 | { | ||
225 | mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS")*1024; | ||
226 | resetDynamicThrottle(); | ||
227 | mCurrent.dump(); | ||
228 | } | ||
229 | |||
230 | |||
231 | void LLViewerThrottle::save() const | ||
232 | { | ||
233 | gSavedSettings.setF32("ThrottleBandwidthKBPS", mMaxBandwidth/1024); | ||
234 | } | ||
235 | |||
236 | |||
237 | void LLViewerThrottle::sendToSim() const | ||
238 | { | ||
239 | mCurrent.sendToSim(); | ||
240 | } | ||
241 | |||
242 | |||
243 | LLViewerThrottleGroup 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 | ||
290 | void LLViewerThrottle::resetDynamicThrottle() | ||
291 | { | ||
292 | mThrottleFrac = MAX_FRACTIONAL; | ||
293 | |||
294 | mCurrentBandwidth = mMaxBandwidth*MAX_FRACTIONAL; | ||
295 | mCurrent = getThrottleGroup(mCurrentBandwidth / 1024.0f); | ||
296 | } | ||
297 | |||
298 | void 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 | } | ||