diff options
| -rw-r--r-- | indra/llcommon/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | indra/llcommon/llstatsaccumulator.h | 120 | ||||
| -rw-r--r-- | indra/llcorehttp/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpoprequest.cpp | 6 | ||||
| -rw-r--r-- | indra/llcorehttp/_httppolicy.cpp | 3 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpservice.cpp | 49 | ||||
| -rw-r--r-- | indra/llcorehttp/bufferarray.cpp | 22 | ||||
| -rw-r--r-- | indra/llcorehttp/httprequest.cpp | 12 | ||||
| -rw-r--r-- | indra/llcorehttp/httprequest.h | 15 | ||||
| -rw-r--r-- | indra/llcorehttp/httpstats.cpp | 82 | ||||
| -rw-r--r-- | indra/llcorehttp/httpstats.h | 70 | ||||
| -rw-r--r-- | indra/newview/llappcorehttp.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llfasttimerview.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llviewerstats.h | 86 | 
14 files changed, 370 insertions, 105 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 142e56dfca..d9eb13d65a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -226,6 +226,7 @@ set(llcommon_HEADER_FILES      llstring.h      llstringtable.h      llstaticstringtable.h +    llstatsaccumulator.h      llsys.h      llthread.h      llthreadlocalstorage.h diff --git a/indra/llcommon/llstatsaccumulator.h b/indra/llcommon/llstatsaccumulator.h new file mode 100644 index 0000000000..a893cc301d --- /dev/null +++ b/indra/llcommon/llstatsaccumulator.h @@ -0,0 +1,120 @@ +/** +* @file llstatsaccumulator.h +* @brief Class for accumulating statistics. +* +* $LicenseInfo:firstyear=2002&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#ifndef LL_STATS_ACCUMULATOR_H +#define  LL_STATS_ACCUMULATOR_H +#include "llsd.h" + +class LLStatsAccumulator +{ +public: +    inline LLStatsAccumulator() +    { +        reset(); +    } + +    inline void push(F32 val) +    { +        if (mCountOfNextUpdatesToIgnore > 0) +        { +            mCountOfNextUpdatesToIgnore--; +            return; +        } + +        mCount++; +        mSum += val; +        mSumOfSquares += val * val; +        if (mCount == 1 || val > mMaxValue) +        { +            mMaxValue = val; +        } +        if (mCount == 1 || val < mMinValue) +        { +            mMinValue = val; +        } +    } + +    inline F32 getSum() const +    { +        return mSum; +    } + +    inline F32 getMean() const +    { +        return (mCount == 0) ? 0.f : ((F32)mSum) / mCount; +    } + +    inline F32 getMinValue() const +    { +        return mMinValue; +    } + +    inline F32 getMaxValue() const +    { +        return mMaxValue; +    } + +    inline F32 getStdDev() const +    { +        const F32 mean = getMean(); +        return (mCount < 2) ? 0.f : sqrt(llmax(0.f, mSumOfSquares / mCount - (mean * mean))); +    } + +    inline U32 getCount() const +    { +        return mCount; +    } + +    inline void reset() +    { +        mCount = 0; +        mSum = mSumOfSquares = 0.f; +        mMinValue = 0.0f; +        mMaxValue = 0.0f; +        mCountOfNextUpdatesToIgnore = 0; +    } + +    inline LLSD asLLSD() const +    { +        LLSD data; +        data["mean"] = getMean(); +        data["std_dev"] = getStdDev(); +        data["count"] = (S32)mCount; +        data["min"] = getMinValue(); +        data["max"] = getMaxValue(); +        return data; +    } + +private: +    S32 mCount; +    F32 mSum; +    F32 mSumOfSquares; +    F32 mMinValue; +    F32 mMaxValue; +    U32 mCountOfNextUpdatesToIgnore; +}; + +#endif diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 7482fc577f..435fb09aa4 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -30,6 +30,7 @@ set(llcorehttp_SOURCE_FILES      httpoptions.cpp      httprequest.cpp      httpresponse.cpp +    httpstats.cpp      _httplibcurl.cpp      _httpopcancel.cpp      _httpoperation.cpp @@ -57,6 +58,7 @@ set(llcorehttp_HEADER_FILES      httpoptions.h      httprequest.h      httpresponse.h +    httpstats.h      _httpinternal.h      _httplibcurl.h      _httpopcancel.h diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 07cc0e4625..f35f9848ff 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -47,6 +47,8 @@  #include "llhttpconstants.h"  #include "llproxy.h" +#include "httpstats.h" +  // *DEBUG:  "[curl:bugs] #1420" problem and testing.  //  // A pipelining problem, https://sourceforge.net/p/curl/bugs/1420/, @@ -805,6 +807,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void  	}  	const size_t req_size(size * nmemb);  	const size_t write_size(op->mReplyBody->append(static_cast<char *>(data), req_size)); +    HTTPStats::instance().recordDataDown(write_size);  	return write_size;  } @@ -833,7 +836,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void  	const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos));  	const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size)); -	op->mCurlBodyPos += read_size; +    HTTPStats::instance().recordDataUp(read_size); +    op->mCurlBodyPos += read_size;  	return read_size;  } diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index b2709b53ec..628a5c79e1 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -34,6 +34,7 @@  #include "_httppolicyclass.h"  #include "lltimer.h" +#include "httpstats.h"  namespace  { @@ -448,6 +449,8 @@ bool HttpPolicy::stageAfterCompletion(const HttpOpRequest::ptr_t &op)  	}  	op->stageFromActive(mService); + +    HTTPStats::instance().recordResultCode(op->mStatus.getStatus());  	return false;						// not active  } diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 6c39fdc61b..49d865cbfa 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -38,7 +38,8 @@  #include "lltimer.h"  #include "llthread.h" - +#include "llexception.h" +#include "llmemory.h"  namespace  { @@ -293,22 +294,42 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)  	ELoopSpeed loop(REQUEST_SLEEP);  	while (! mExitRequested)  	{ -		loop = processRequestQueue(loop); +        try +        { +		    loop = processRequestQueue(loop); -		// Process ready queue issuing new requests as needed -		ELoopSpeed new_loop = mPolicy->processReadyQueue(); -		loop = (std::min)(loop, new_loop); +		    // Process ready queue issuing new requests as needed +		    ELoopSpeed new_loop = mPolicy->processReadyQueue(); +		    loop = (std::min)(loop, new_loop); -		// Give libcurl some cycles -		new_loop = mTransport->processTransport(); -		loop = (std::min)(loop, new_loop); +		    // Give libcurl some cycles +		    new_loop = mTransport->processTransport(); +		    loop = (std::min)(loop, new_loop); -		// Determine whether to spin, sleep briefly or sleep for next request -		if (REQUEST_SLEEP != loop) -		{ -			ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS); -		} -	} +		    // Determine whether to spin, sleep briefly or sleep for next request +		    if (REQUEST_SLEEP != loop) +		    { +			    ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS); +		    } +        } +        catch (const LLContinueError&) +        { +            LOG_UNHANDLED_EXCEPTION(""); +        } +        catch (std::bad_alloc) +        { +            LLMemory::logMemoryInfo(TRUE); + +            //output possible call stacks to log file. +            LLError::LLCallStacks::print(); + +            LL_ERRS() << "Bad memory allocation in HttpService::threadRun()!" << LL_ENDL; +        } +        catch (...) +        { +            CRASH_ON_UNHANDLED_EXCEPTION(""); +        } +    }  	shutdown();  	sState = STOPPED; diff --git a/indra/llcorehttp/bufferarray.cpp b/indra/llcorehttp/bufferarray.cpp index 8eaaeed710..be534b3ce4 100644 --- a/indra/llcorehttp/bufferarray.cpp +++ b/indra/llcorehttp/bufferarray.cpp @@ -25,6 +25,8 @@   */  #include "bufferarray.h" +#include "llexception.h" +#include "llmemory.h"  // BufferArray is a list of chunks, each a BufferArray::Block, of contiguous @@ -140,8 +142,22 @@ size_t BufferArray::append(const void * src, size_t len)  		{  			mBlocks.reserve(mBlocks.size() + 5);  		} -		Block * block = Block::alloc(BLOCK_ALLOC_SIZE); -		memcpy(block->mData, c_src, copy_len); +        Block * block; +        try +        { +            block = Block::alloc(BLOCK_ALLOC_SIZE); +        } +        catch (std::bad_alloc) +        { +            LLMemory::logMemoryInfo(TRUE); + +            //output possible call stacks to log file. +            LLError::LLCallStacks::print(); + +            LL_WARNS() << "Bad memory allocation in thrown by Block::alloc in read!" << LL_ENDL; +            break; +        } +        memcpy(block->mData, c_src, copy_len);  		block->mUsed = copy_len;  		llassert_always(block->mUsed <= block->mAlloced);  		mBlocks.push_back(block); @@ -149,7 +165,7 @@ size_t BufferArray::append(const void * src, size_t len)  		c_src += copy_len;  		len -= copy_len;  	} -	return ret; +	return ret - len;  } diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index e09f0c3b18..d9662c1232 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -37,7 +37,7 @@  #include "_httpopsetget.h"  #include "lltimer.h" - +#include "httpstats.h"  namespace  { @@ -52,6 +52,7 @@ namespace LLCore  // ====================================  // HttpRequest Implementation  // ==================================== +HttpRequest::Statistics HttpRequest::mStatistics;  HttpRequest::HttpRequest() @@ -62,6 +63,12 @@ HttpRequest::HttpRequest()  	mRequestQueue->addRef();  	mReplyQueue.reset( new HttpReplyQueue() ); + +    ++mStatistics.mCurrentRequests; +    ++mStatistics.mTotalRequests; + +     +    LL_WARNS("HTTPRequest") << "New HttpRequest created (outstanding: " << mStatistics.mCurrentRequests << " total: " << mStatistics.mTotalRequests << ")" << LL_ENDL;  } @@ -74,6 +81,9 @@ HttpRequest::~HttpRequest()  	}      mReplyQueue.reset(); +    --mStatistics.mCurrentRequests; + +    LL_WARNS("HTTPRequest") << "HttpRequest destroyed (outstanding: " << mStatistics.mCurrentRequests << " total: " << mStatistics.mTotalRequests << ")" << LL_ENDL;  } diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index 17cfdcd7b6..c958132ae2 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -680,7 +680,20 @@ private:  	/// @}  	// End Global State  	// ==================================== -	 + +    struct Statistics +    { +        Statistics(): +            mTotalRequests(0), +            mCurrentRequests(0) +        {} + +        S32 mTotalRequests; +        S32 mCurrentRequests; +    }; + +    static Statistics mStatistics; +  };  // end class HttpRequest diff --git a/indra/llcorehttp/httpstats.cpp b/indra/llcorehttp/httpstats.cpp new file mode 100644 index 0000000000..467d364885 --- /dev/null +++ b/indra/llcorehttp/httpstats.cpp @@ -0,0 +1,82 @@ +/**  + * @file llviewerstats.cpp + * @brief LLViewerStats class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "httpstats.h" +#include "llerror.h" + +namespace LLCore +{ +HTTPStats::HTTPStats() +{ +    resetStats(); +} + + +HTTPStats::~HTTPStats() +{ +} + +void HTTPStats::resetStats() +{ +    mResutCodes.clear(); +    mDataDown.reset(); +    mDataUp.reset(); +} + + +void HTTPStats::recordResultCode(S32 code) +{ +    std::map<S32, S32>::iterator it; + +    it = mResutCodes.find(code); + +    if (it == mResutCodes.end()) +        mResutCodes[code] = 1; +    else +        (*it).second = (*it).second + 1; + +} + +void HTTPStats::dumpStats() +{ +    std::stringstream out; + +    out << "HTTPCore Stats" << std::endl; +    out << "Bytes Sent: " << mDataUp.getSum() << std::endl; +    out << "Bytes Recv: " << mDataDown.getSum() << std::endl; +    out << "Result Codes:" << std::endl << "--- -----" << std::endl; + + +    for (std::map<S32, S32>::iterator it = mResutCodes.begin(); it != mResutCodes.end(); ++it) +    {  +        out << (*it).first << " " << (*it).second << std::endl; +    } + +    LL_WARNS("HTTP Core") << out.str() << LL_ENDL; +} + + +} diff --git a/indra/llcorehttp/httpstats.h b/indra/llcorehttp/httpstats.h new file mode 100644 index 0000000000..d4460bcfae --- /dev/null +++ b/indra/llcorehttp/httpstats.h @@ -0,0 +1,70 @@ +/**  + * @file llviewerim_peningtats.h + * @brief LLViewerStats class header file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERSTATS_H +#define LL_LLVIEWERSTATS_H + +#include "lltracerecording.h" +#include "lltrace.h" +#include "llstatsaccumulator.h" +#include "llsingleton.h" +#include "llsd.h" + +namespace LLCore +{ +    class HTTPStats : public LLSingleton<HTTPStats> +    { +        LLSINGLETON(HTTPStats); +        virtual ~HTTPStats(); + +    public: +        void resetStats(); + +        typedef LLStatsAccumulator StatsAccumulator; + +        void    recordDataDown(size_t bytes) +        { +            mDataDown.push(bytes); +        } + +        void    recordDataUp(size_t bytes) +        { +            mDataUp.push(bytes); +        } + +        void    recordResultCode(S32 code); + +        void    dumpStats(); +    private: +        StatsAccumulator mDataDown; +        StatsAccumulator mDataUp; + +        std::map<S32, S32> mResutCodes; +    }; + + +} +#endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index c1f898284a..261a7b5ad9 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -39,6 +39,7 @@  #include <curl/curl.h>  #include "llcorehttputil.h" +#include "httpstats.h"  // Here is where we begin to get our connection usage under control.  // This establishes llcorehttp policy classes that, among other @@ -313,6 +314,8 @@ void LLAppCoreHttp::requestStop()  void LLAppCoreHttp::cleanup()  { +    LLCore::HTTPStats::instance().dumpStats(); +  	if (LLCORE_HTTP_HANDLE_INVALID == mStopHandle)  	{  		// Should have been started already... diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index a69b3b7dc7..91501ccb1f 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -796,13 +796,13 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)  	for(stats_map_t::iterator it = time_stats.begin(); it != time_stats.end(); ++it)  	{  		std::string label = it->first; -		ret[label]["TotalTime"] = time_stats[label].mSum; +		ret[label]["TotalTime"] = time_stats[label].getSum();  		ret[label]["MeanTime"] = time_stats[label].getMean();  		ret[label]["MaxTime"] = time_stats[label].getMaxValue();  		ret[label]["MinTime"] = time_stats[label].getMinValue();  		ret[label]["StdDevTime"] = time_stats[label].getStdDev(); -		ret[label]["Samples"] = sample_stats[label].mSum; +        ret[label]["Samples"] = sample_stats[label].getSum();  		ret[label]["MaxSamples"] = sample_stats[label].getMaxValue();  		ret[label]["MinSamples"] = sample_stats[label].getMinValue();  		ret[label]["StdDevSamples"] = sample_stats[label].getStdDev(); diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 97a060d95e..d8d92d61d3 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -30,7 +30,7 @@  #include "lltextureinfo.h"  #include "lltracerecording.h"  #include "lltrace.h" - +#include "llstatsaccumulator.h"  enum ESimStatID  { @@ -256,89 +256,9 @@ public:  	void addToMessage(LLSD &body); -	struct  StatsAccumulator -	{ -		S32 mCount; -		F32 mSum; -		F32 mSumOfSquares; -		F32 mMinValue; -		F32 mMaxValue; -		U32 mCountOfNextUpdatesToIgnore; - -		inline StatsAccumulator() -		{ -			reset(); -		} - -		inline void push( F32 val ) -		{ -			if ( mCountOfNextUpdatesToIgnore > 0 ) -			{ -				mCountOfNextUpdatesToIgnore--; -				return; -			} -			 -			mCount++; -			mSum += val; -			mSumOfSquares += val * val; -			if (mCount == 1 || val > mMaxValue) -			{ -				mMaxValue = val; -			} -			if (mCount == 1 || val < mMinValue) -			{ -				mMinValue = val; -			} -		} -		 -		inline F32 getMean() const -		{ -			return (mCount == 0) ? 0.f : ((F32)mSum)/mCount; -		} - -		inline F32 getMinValue() const -		{ -			return mMinValue; -		} - -		inline F32 getMaxValue() const -		{ -			return mMaxValue; -		} - -		inline F32 getStdDev() const -		{ -			const F32 mean = getMean(); -			return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean))); -		} -		 -		inline U32 getCount() const -		{ -			return mCount; -		} - -		inline void reset() -		{ -			mCount = 0; -			mSum = mSumOfSquares = 0.f; -			mMinValue = 0.0f; -			mMaxValue = 0.0f; -			mCountOfNextUpdatesToIgnore = 0; -		} -		 -		inline LLSD asLLSD() const -		{ -			LLSD data; -			data["mean"] = getMean(); -			data["std_dev"] = getStdDev(); -			data["count"] = (S32)mCount; -			data["min"] = getMinValue(); -			data["max"] = getMaxValue(); -			return data; -		} -	}; +    typedef LLStatsAccumulator StatsAccumulator; -	// Phase tracking (originally put in for avatar rezzing), tracking +    // Phase tracking (originally put in for avatar rezzing), tracking  	// progress of active/completed phases for activities like outfit changing.  	typedef std::map<std::string,LLTimer>	phase_map_t;  	typedef std::map<std::string,StatsAccumulator>	phase_stats_t; | 
