PageRenderTime 56ms CodeModel.GetById 15ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llmetricperformancetester.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 336 lines | 226 code | 52 blank | 58 comment | 36 complexity | d6351d0b9a7d45dea12e762b2a408426 MD5 | raw file
  1/** 
  2 * @file llmetricperformancetester.cpp
  3 * @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes implementation
  4 *
  5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "indra_constants.h"
 30#include "llerror.h"
 31#include "llsdserialize.h"
 32#include "llstat.h"
 33#include "lltreeiterators.h"
 34#include "llmetricperformancetester.h"
 35
 36//----------------------------------------------------------------------------------------------
 37// LLMetricPerformanceTesterBasic : static methods and testers management
 38//----------------------------------------------------------------------------------------------
 39
 40LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
 41
 42/*static*/ 
 43void LLMetricPerformanceTesterBasic::cleanClass() 
 44{
 45	for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
 46	{
 47		delete iter->second ;
 48	}
 49	sTesterMap.clear() ;
 50}
 51
 52/*static*/ 
 53BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester) 
 54{
 55	llassert_always(tester != NULL);	
 56	std::string name = tester->getTesterName() ;
 57	if (getTester(name))
 58	{
 59		llerrs << "Tester name is already used by some other tester : " << name << llendl ;
 60		return FALSE;
 61	}
 62
 63	sTesterMap.insert(std::make_pair(name, tester));
 64	return TRUE;
 65}
 66
 67/*static*/ 
 68void LLMetricPerformanceTesterBasic::deleteTester(std::string name)
 69{
 70	name_tester_map_t::iterator tester = sTesterMap.find(name);
 71	if (tester != sTesterMap.end())
 72	{
 73		delete tester->second;
 74		sTesterMap.erase(tester);
 75	}
 76}
 77
 78/*static*/ 
 79LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name) 
 80{
 81	// Check for the requested metric name
 82	name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
 83	if (found_it != sTesterMap.end())
 84	{
 85		return found_it->second ;
 86	}
 87	return NULL ;
 88}
 89
 90/*static*/ 
 91// Return TRUE if this metric is requested or if the general default "catch all" metric is requested
 92BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
 93{
 94	return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
 95}
 96
 97/*static*/ 
 98LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& is)
 99{
100	LLSD ret;
101	LLSD cur;
102	
103	while (!is.eof() && LLSDSerialize::fromXML(cur, is))
104	{
105		for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
106		{
107			std::string label = iter->first;
108			
109			LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
110			if(tester)
111			{
112				ret[label]["Name"] = iter->second["Name"] ;
113				
114				S32 num_of_metrics = tester->getNumberOfMetrics() ;
115				for(S32 index = 0 ; index < num_of_metrics ; index++)
116				{
117					ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
118				}
119			}
120		}
121	}
122	
123	return ret;
124}
125
126/*static*/ 
127void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
128{
129	if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
130	{
131		return ;
132	}
133	
134	// Open baseline and current target, exit if one is inexistent
135	std::ifstream base_is(baseline.c_str());
136	std::ifstream target_is(target.c_str());
137	if (!base_is.is_open() || !target_is.is_open())
138	{
139		llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
140		base_is.close();
141		target_is.close();
142		return;
143	}
144	
145	//analyze baseline
146	LLSD base = analyzeMetricPerformanceLog(base_is);
147	base_is.close();
148	
149	//analyze current
150	LLSD current = analyzeMetricPerformanceLog(target_is);
151	target_is.close();
152	
153	//output comparision
154	std::ofstream os(output.c_str());
155	
156	os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n"; 
157	for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ; 
158		iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
159	{
160		LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;	
161		tester->analyzePerformance(&os, &base, &current) ;
162	}
163	
164	os.flush();
165	os.close();
166}
167
168
169//----------------------------------------------------------------------------------------------
170// LLMetricPerformanceTesterBasic : Tester instance methods
171//----------------------------------------------------------------------------------------------
172
173LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) : 
174	mName(name),
175	mCount(0)
176{
177	if (mName == std::string())
178	{
179		llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
180	}
181
182	mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
183}
184
185LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic() 
186{
187}
188
189void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd) 
190{
191	incrementCurrentCount() ;
192	(*sd)[getCurrentLabelName()]["Name"] = mName ;
193}
194
195void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
196{
197	LLMutexLock lock(LLFastTimer::sLogLock);
198	LLFastTimer::sLogQueue.push((*sd));
199}
200
201void LLMetricPerformanceTesterBasic::outputTestResults() 
202{
203	LLSD sd;
204
205	preOutputTestResults(&sd) ; 
206	outputTestRecord(&sd) ;
207	postOutputTestResults(&sd) ;
208}
209
210void LLMetricPerformanceTesterBasic::addMetric(std::string str)
211{
212	mMetricStrings.push_back(str) ;
213}
214
215/*virtual*/ 
216void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) 
217{
218	resetCurrentCount() ;
219
220	std::string current_label = getCurrentLabelName();
221	BOOL in_base = (*base).has(current_label) ;
222	BOOL in_current = (*current).has(current_label) ;
223
224	while(in_base || in_current)
225	{
226		LLSD::String label = current_label ;		
227
228		if(in_base && in_current)
229		{				
230			*os << llformat("%s\n", label.c_str()) ;
231
232			for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
233			{
234				switch((*current)[label][ mMetricStrings[index] ].type())
235				{
236				case LLSD::TypeInteger:
237					compareTestResults(os, mMetricStrings[index], 
238						(S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
239					break ;
240				case LLSD::TypeReal:
241					compareTestResults(os, mMetricStrings[index], 
242						(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
243					break;
244				default:
245					llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
246				}
247			}	
248		}
249
250		incrementCurrentCount();
251		current_label = getCurrentLabelName();
252		in_base = (*base).has(current_label) ;
253		in_current = (*current).has(current_label) ;
254	}
255}
256
257/*virtual*/ 
258void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) 
259{
260	*os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current, 
261						v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
262}
263
264/*virtual*/ 
265void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) 
266{
267	*os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,						
268						v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
269}
270
271//----------------------------------------------------------------------------------------------
272// LLMetricPerformanceTesterWithSession
273//----------------------------------------------------------------------------------------------
274
275LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) : 
276	LLMetricPerformanceTesterBasic(name),
277	mBaseSessionp(NULL),
278	mCurrentSessionp(NULL)
279{
280}
281
282LLMetricPerformanceTesterWithSession::~LLMetricPerformanceTesterWithSession()
283{
284	if (mBaseSessionp)
285	{
286		delete mBaseSessionp ;
287		mBaseSessionp = NULL ;
288	}
289	if (mCurrentSessionp)
290	{
291		delete mCurrentSessionp ;
292		mCurrentSessionp = NULL ;
293	}
294}
295
296/*virtual*/ 
297void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) 
298{
299	// Load the base session
300	resetCurrentCount() ;
301	mBaseSessionp = loadTestSession(base) ;
302
303	// Load the current session
304	resetCurrentCount() ;
305	mCurrentSessionp = loadTestSession(current) ;
306
307	if (!mBaseSessionp || !mCurrentSessionp)
308	{
309		llerrs << "Error loading test sessions." << llendl ;
310	}
311
312	// Compare
313	compareTestSessions(os) ;
314
315	// Release memory
316	if (mBaseSessionp)
317	{
318		delete mBaseSessionp ;
319		mBaseSessionp = NULL ;
320	}
321	if (mCurrentSessionp)
322	{
323		delete mCurrentSessionp ;
324		mCurrentSessionp = NULL ;
325	}
326}
327
328
329//----------------------------------------------------------------------------------------------
330// LLTestSession
331//----------------------------------------------------------------------------------------------
332
333LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession() 
334{
335}
336