| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "NativeFeatureIncludes.h"
- #if _RAKNET_SUPPORT_StatisticsHistory==1
- #include "StatisticsHistory.h"
- #include "GetTime.h"
- #include "RakNetStatistics.h"
- #include "RakPeerInterface.h"
- using namespace RakNet;
- STATIC_FACTORY_DEFINITIONS(StatisticsHistory,StatisticsHistory);
- STATIC_FACTORY_DEFINITIONS(StatisticsHistoryPlugin,StatisticsHistoryPlugin);
- int StatisticsHistory::TrackedObjectComp( const uint64_t &key, StatisticsHistory::TrackedObject* const &data )
- {
- if (key < data->trackedObjectData.objectId)
- return -1;
- if (key == data->trackedObjectData.objectId)
- return 0;
- return 1;
- }
- int TimeAndValueQueueCompAsc( StatisticsHistory::TimeAndValueQueue* const &key, StatisticsHistory::TimeAndValueQueue* const &data )
- {
- if (key->sortValue < data->sortValue)
- return -1;
- if (key->sortValue > data->sortValue)
- return 1;
- if (key->key < data->key)
- return -1;
- if (key->key > data->key)
- return 1;
- return 0;
- }
- int TimeAndValueQueueCompDesc( StatisticsHistory::TimeAndValueQueue* const &key, StatisticsHistory::TimeAndValueQueue* const &data )
- {
- if (key->sortValue > data->sortValue)
- return -1;
- if (key->sortValue < data->sortValue)
- return 1;
- if (key->key > data->key)
- return -1;
- if (key->key < data->key)
- return 1;
- return 0;
- }
- StatisticsHistory::TrackedObjectData::TrackedObjectData() {}
- StatisticsHistory::TrackedObjectData::TrackedObjectData(uint64_t _objectId, int _objectType, void *_userData)
- {
- objectId=_objectId;
- objectType=_objectType;
- userData=_userData;
- }
- StatisticsHistory::StatisticsHistory() {timeToTrack = 30000;}
- StatisticsHistory::~StatisticsHistory()
- {
- Clear();
- }
- void StatisticsHistory::SetDefaultTimeToTrack(Time defaultTimeToTrack) {timeToTrack = defaultTimeToTrack;}
- Time StatisticsHistory::GetDefaultTimeToTrack(void) const {return timeToTrack;}
- bool StatisticsHistory::AddObject(TrackedObjectData tod)
- {
- bool objectExists;
- unsigned int idx = objects.GetIndexFromKey(tod.objectId, &objectExists);
- if (objectExists)
- return false;
- TrackedObject *to = RakNet::OP_NEW<TrackedObject>(_FILE_AND_LINE_);
- to->trackedObjectData=tod;
- objects.InsertAtIndex(to,idx,_FILE_AND_LINE_);
- return true;
- }
- bool StatisticsHistory::RemoveObject(uint64_t objectId, void **userData)
- {
- unsigned int idx = GetObjectIndex(objectId);
- if (idx == (unsigned int) -1)
- return false;
- if (userData)
- *userData = objects[idx]->trackedObjectData.userData;
- RemoveObjectAtIndex(idx);
- return true;
- }
- void StatisticsHistory::RemoveObjectAtIndex(unsigned int index)
- {
- TrackedObject *to = objects[index];
- objects.RemoveAtIndex(index);
- RakNet::OP_DELETE(to, _FILE_AND_LINE_);
- }
- void StatisticsHistory::Clear(void)
- {
- for (unsigned int idx=0; idx < objects.Size(); idx++)
- {
- RakNet::OP_DELETE(objects[idx], _FILE_AND_LINE_);
- }
- objects.Clear(false, _FILE_AND_LINE_);
- }
- unsigned int StatisticsHistory::GetObjectCount(void) const {return objects.Size();}
- StatisticsHistory::TrackedObjectData * StatisticsHistory::GetObjectAtIndex(unsigned int index) const {return &objects[index]->trackedObjectData;}
- bool StatisticsHistory::AddValueByObjectID(uint64_t objectId, RakString key, SHValueType val, Time curTime, bool combineEqualTimes)
- {
- unsigned int idx = GetObjectIndex(objectId);
- if (idx == (unsigned int) -1)
- return false;
- AddValueByIndex(idx, key, val, curTime, combineEqualTimes);
- return true;
- }
- void StatisticsHistory::AddValueByIndex(unsigned int index, RakString key, SHValueType val, Time curTime, bool combineEqualTimes)
- {
- TimeAndValueQueue *queue;
- TrackedObject *to = objects[index];
- DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
- if (hi.IsInvalid())
- {
- queue = RakNet::OP_NEW<TimeAndValueQueue>(_FILE_AND_LINE_);
- queue->key=key;
- queue->timeToTrackValues = timeToTrack;
- to->dataQueues.Push(key, queue, _FILE_AND_LINE_);
- }
- else
- {
- queue = to->dataQueues.ItemAtIndex(hi);
- }
- TimeAndValue tav;
- if (combineEqualTimes==true && queue->values.Size()>0 && queue->values.PeekTail().time==curTime)
- {
- tav = queue->values.PopTail();
- queue->recentSum -= tav.val;
- queue->recentSumOfSquares -= tav.val * tav.val;
- queue->longTermSum -= tav.val;
- queue->longTermCount = queue->longTermCount - 1;
- }
- else
- {
- tav.val=0.0;
- tav.time=curTime;
- }
- tav.val+=val;
- queue->values.Push(tav, _FILE_AND_LINE_);
- queue->recentSum += tav.val;
- queue->recentSumOfSquares += tav.val * tav.val;
- queue->longTermSum += tav.val;
- queue->longTermCount = queue->longTermCount + 1;
- if (queue->longTermLowest > tav.val)
- queue->longTermLowest = tav.val;
- if (queue->longTermHighest < tav.val)
- queue->longTermHighest = tav.val;
- }
- StatisticsHistory::SHErrorCode StatisticsHistory::GetHistoryForKey(uint64_t objectId, RakString key, StatisticsHistory::TimeAndValueQueue **values, Time curTime) const
- {
- if (values == 0)
- return SH_INVALID_PARAMETER;
- unsigned int idx = GetObjectIndex(objectId);
- if (idx == (unsigned int) -1)
- return SH_UKNOWN_OBJECT;
- TrackedObject *to = objects[idx];
- DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
- if (hi.IsInvalid())
- return SH_UKNOWN_KEY;
- *values = to->dataQueues.ItemAtIndex(hi);
- (*values)->CullExpiredValues(curTime);
- return SH_OK;
- }
- bool StatisticsHistory::GetHistorySorted(uint64_t objectId, SHSortOperation sortType, DataStructures::List<StatisticsHistory::TimeAndValueQueue *> &values) const
- {
- unsigned int idx = GetObjectIndex(objectId);
- if (idx == (unsigned int) -1)
- return false;
- TrackedObject *to = objects[idx];
- DataStructures::List<TimeAndValueQueue*> itemList;
- DataStructures::List<RakString> keyList;
- to->dataQueues.GetAsList(itemList,keyList,_FILE_AND_LINE_);
- Time curTime = GetTime();
- DataStructures::OrderedList<TimeAndValueQueue*, TimeAndValueQueue*,TimeAndValueQueueCompAsc> sortedQueues;
- for (unsigned int i=0; i < itemList.Size(); i++)
- {
- TimeAndValueQueue *tavq = itemList[i];
- tavq->CullExpiredValues(curTime);
- if (sortType == SH_SORT_BY_RECENT_SUM_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_DESCENDING)
- tavq->sortValue = tavq->GetRecentSum();
- else if (sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_SUM_DESCENDING)
- tavq->sortValue = tavq->GetLongTermSum();
- else if (sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_DESCENDING)
- tavq->sortValue = tavq->GetRecentSumOfSquares();
- else if (sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING || sortType == SH_SORT_BY_RECENT_AVERAGE_DESCENDING)
- tavq->sortValue = tavq->GetRecentAverage();
- else if (sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_AVERAGE_DESCENDING)
- tavq->sortValue = tavq->GetLongTermAverage();
- else if (sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING || sortType == SH_SORT_BY_RECENT_HIGHEST_DESCENDING)
- tavq->sortValue = tavq->GetRecentHighest();
- else if (sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING || sortType == SH_SORT_BY_RECENT_LOWEST_DESCENDING)
- tavq->sortValue = tavq->GetRecentLowest();
- else if (sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_HIGHEST_DESCENDING)
- tavq->sortValue = tavq->GetLongTermHighest();
- else
- tavq->sortValue = tavq->GetLongTermLowest();
- if (
- sortType == SH_SORT_BY_RECENT_SUM_ASCENDING ||
- sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING ||
- sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING ||
- sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING ||
- sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING ||
- sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING ||
- sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING ||
- sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING ||
- sortType == SH_SORT_BY_LONG_TERM_LOWEST_ASCENDING)
- sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompAsc);
- else
- sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompDesc);
- }
- for (unsigned int i=0; i < sortedQueues.Size(); i++)
- values.Push(sortedQueues[i], _FILE_AND_LINE_);
- return true;
- }
- void StatisticsHistory::MergeAllObjectsOnKey(RakString key, TimeAndValueQueue *tavqOutput, SHDataCategory dataCategory) const
- {
- tavqOutput->Clear();
- Time curTime = GetTime();
- // Find every object with this key
- for (unsigned int idx=0; idx < objects.Size(); idx++)
- {
- TrackedObject *to = objects[idx];
- DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
- if (hi.IsInvalid()==false)
- {
- TimeAndValueQueue *tavqInput = to->dataQueues.ItemAtIndex(hi);
- tavqInput->CullExpiredValues(curTime);
- TimeAndValueQueue::MergeSets(tavqOutput, dataCategory, tavqInput, dataCategory, tavqOutput);
- }
- }
- }
- void StatisticsHistory::GetUniqueKeyList(DataStructures::List<RakString> &keys)
- {
- keys.Clear(true, _FILE_AND_LINE_);
- for (unsigned int idx=0; idx < objects.Size(); idx++)
- {
- TrackedObject *to = objects[idx];
- DataStructures::List<TimeAndValueQueue*> itemList;
- DataStructures::List<RakNet::RakString> keyList;
- to->dataQueues.GetAsList(itemList, keyList, _FILE_AND_LINE_);
- for (unsigned int k=0; k < keyList.Size(); k++)
- {
- bool hasKey=false;
- for (unsigned int j=0; j < keys.Size(); j++)
- {
- if (keys[j]==keyList[k])
- {
- hasKey=true;
- break;
- }
- }
- if (hasKey==false)
- keys.Push(keyList[k], _FILE_AND_LINE_);
- }
- }
- }
- StatisticsHistory::TimeAndValueQueue::TimeAndValueQueue()
- {
- Clear();
- }
- StatisticsHistory::TimeAndValueQueue::~TimeAndValueQueue(){}
- void StatisticsHistory::TimeAndValueQueue::SetTimeToTrackValues(Time t)
- {
- timeToTrackValues = t;
- }
- Time StatisticsHistory::TimeAndValueQueue::GetTimeToTrackValues(void) const {return timeToTrackValues;}
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentSum(void) const {return recentSum;}
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentSumOfSquares(void) const {return recentSumOfSquares;}
- SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermSum(void) const {return longTermSum;}
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentAverage(void) const
- {
- if (values.Size() > 0)
- return recentSum / (SHValueType) values.Size();
- else
- return 0;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentLowest(void) const
- {
- SHValueType out = SH_TYPE_MAX;
- for (unsigned int idx=0; idx < values.Size(); idx++)
- {
- if (values[idx].val < out)
- out = values[idx].val;
- }
- return out;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentHighest(void) const
- {
- SHValueType out = -SH_TYPE_MAX;
- for (unsigned int idx=0; idx < values.Size(); idx++)
- {
- if (values[idx].val > out)
- out = values[idx].val;
- }
- return out;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentStandardDeviation(void) const
- {
- if (values.Size()==0)
- return 0;
- SHValueType recentMean= GetRecentAverage();
- SHValueType squareOfMean = recentMean * recentMean;
- SHValueType meanOfSquares = GetRecentSumOfSquares() / (SHValueType) values.Size();
- return meanOfSquares - squareOfMean;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermAverage(void) const
- {
- if (longTermCount == 0)
- return 0;
- return longTermSum / longTermCount;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermLowest(void) const {return longTermLowest;}
- SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermHighest(void) const {return longTermHighest;}
- Time StatisticsHistory::TimeAndValueQueue::GetTimeRange(void) const
- {
- if (values.Size()<2)
- return 0;
- return values[values.Size()-1].time - values[0].time;
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::GetSumSinceTime(Time t) const
- {
- SHValueType sum = 0;
- for (int i=values.Size(); i > 0; --i)
- {
- if (values[i-1].time>=t)
- sum+=values[i-1].val;
- }
- return sum;
- }
- void StatisticsHistory::TimeAndValueQueue::MergeSets( const TimeAndValueQueue *lhs, SHDataCategory lhsDataCategory, const TimeAndValueQueue *rhs, SHDataCategory rhsDataCategory, TimeAndValueQueue *output )
- {
- // Two ways to merge:
- // 1. Treat rhs as just more data points.
- // 1A. Sums are just added. If two values have the same time, just put in queue twice
- // 1B. longTermLowest and longTermHighest are the lowest and highest of the two sets
- //
- // 2. Add by time. If time for the other set is missing, calculate slope to extrapolate
- // 2A. Have to recalculate recentSum, recentSumOfSquares.
- // 2B. longTermSum, longTermCount, longTermLowest, longTermHighest are unknown
- if (lhs!=output)
- {
- output->key = lhs->key;
- output->timeToTrackValues = lhs->timeToTrackValues;
- }
- else
- {
- output->key = rhs->key;
- output->timeToTrackValues = rhs->timeToTrackValues;
- }
- unsigned int lhsIndex, rhsIndex;
- lhsIndex=0;
- rhsIndex=0;
- // I use local valuesOutput in case lhs==output || rhs==output
- DataStructures::Queue<TimeAndValue> valuesOutput;
- if (lhsDataCategory==StatisticsHistory::DC_DISCRETE && rhsDataCategory==StatisticsHistory::DC_DISCRETE)
- {
- while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
- {
- if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
- {
- valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
- rhsIndex++;
- }
- else if (rhs->values[rhsIndex].time > lhs->values[lhsIndex].time)
- {
- valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
- lhsIndex++;
- }
- else
- {
- valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
- rhsIndex++;
- valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
- lhsIndex++;
- }
- }
- while (rhsIndex < rhs->values.Size())
- {
- valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
- rhsIndex++;
- }
- while (lhsIndex < lhs->values.Size())
- {
- valuesOutput.Push(lhs->values[lhsIndex], _FILE_AND_LINE_ );
- lhsIndex++;
- }
- output->recentSum = lhs->recentSum + rhs->recentSum;
- output->recentSumOfSquares = lhs->recentSumOfSquares + rhs->recentSumOfSquares;
- output->longTermSum = lhs->longTermSum + rhs->longTermSum;
- output->longTermCount = lhs->longTermCount + rhs->longTermCount;
- if (lhs->longTermLowest < rhs->longTermLowest)
- output->longTermLowest = lhs->longTermLowest;
- else
- output->longTermLowest = rhs->longTermLowest;
- if (lhs->longTermHighest > rhs->longTermHighest)
- output->longTermHighest = lhs->longTermHighest;
- else
- output->longTermHighest = rhs->longTermHighest;
- }
- else
- {
- TimeAndValue lastTimeAndValueLhs, lastTimeAndValueRhs;
- lastTimeAndValueLhs.time=0;
- lastTimeAndValueLhs.val=0;
- lastTimeAndValueRhs.time=0;
- lastTimeAndValueRhs.val=0;
- SHValueType lastSlopeLhs=0;
- SHValueType lastSlopeRhs=0;
- Time timeSinceOppositeValue;
- TimeAndValue newTimeAndValue;
- while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
- {
- if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
- {
- timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
- newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
- newTimeAndValue.time = rhs->values[rhsIndex].time;
- lastTimeAndValueRhs = rhs->values[rhsIndex];
- if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
- lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
- rhsIndex++;
- }
- else if (lhs->values[lhsIndex].time < rhs->values[rhsIndex].time)
- {
- timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
- newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
- newTimeAndValue.time = lhs->values[lhsIndex].time;
- lastTimeAndValueLhs = lhs->values[lhsIndex];
- if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
- lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
- lhsIndex++;
- }
- else
- {
- newTimeAndValue.val = lhs->values[lhsIndex].val + rhs->values[rhsIndex].val;
- newTimeAndValue.time = lhs->values[lhsIndex].time;
- lastTimeAndValueRhs = rhs->values[rhsIndex];
- lastTimeAndValueLhs = lhs->values[lhsIndex];
- if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
- lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
- if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
- lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
- lhsIndex++;
- rhsIndex++;
- }
- valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
- }
- while (rhsIndex < rhs->values.Size())
- {
- timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
- newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
- newTimeAndValue.time = rhs->values[rhsIndex].time;
- valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
- rhsIndex++;
- }
- while (lhsIndex < lhs->values.Size())
- {
- timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
- newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
- newTimeAndValue.time = lhs->values[lhsIndex].time;
- valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
- lhsIndex++;
- }
- output->recentSum = 0;
- output->recentSumOfSquares = 0;
- for (unsigned int i=0; i < valuesOutput.Size(); i++)
- {
- output->recentSum += valuesOutput[i].val;
- output->recentSumOfSquares += valuesOutput[i].val * valuesOutput[i].val;
- }
- }
- output->values = valuesOutput;
- }
- void StatisticsHistory::TimeAndValueQueue::ResizeSampleSet( int maxSamples, DataStructures::Queue<StatisticsHistory::TimeAndValue> &histogram, SHDataCategory dataCategory, Time timeClipStart, Time timeClipEnd )
- {
- histogram.Clear(_FILE_AND_LINE_);
- if (maxSamples==0)
- return;
- Time timeRange = GetTimeRange();
- if (timeRange==0)
- return;
- if (maxSamples==1)
- {
- StatisticsHistory::TimeAndValue tav;
- tav.time = timeRange;
- tav.val = GetRecentSum();
- histogram.Push(tav, _FILE_AND_LINE_);
- return;
- }
- Time interval = timeRange / maxSamples;
- if (interval==0)
- interval=1;
- unsigned int dataIndex;
- Time timeBoundary;
- StatisticsHistory::TimeAndValue currentSum;
- Time currentTime;
- SHValueType numSamples;
- Time endTime;
-
- numSamples=0;
- endTime = values[values.Size()-1].time;
- dataIndex=0;
- currentTime=values[0].time;
- currentSum.val=0;
- currentSum.time=values[0].time + interval / 2;
- timeBoundary = values[0].time + interval;
- while (timeBoundary <= endTime)
- {
- while (dataIndex < values.Size() && values[dataIndex].time <= timeBoundary)
- {
- currentSum.val += values[dataIndex].val;
- dataIndex++;
- numSamples++;
- }
- if (dataCategory==DC_CONTINUOUS)
- {
- if (dataIndex > 0 &&
- dataIndex < values.Size() &&
- values[dataIndex-1].time < timeBoundary &&
- values[dataIndex].time > timeBoundary)
- {
- SHValueType interpolatedValue = Interpolate(values[dataIndex-1], values[dataIndex], timeBoundary);
- currentSum.val+=interpolatedValue;
- numSamples++;
- }
- if (numSamples > 1)
- {
- currentSum.val /= numSamples;
- }
- }
- histogram.Push(currentSum, _FILE_AND_LINE_);
- currentSum.time=timeBoundary + interval / 2;
- timeBoundary += interval;
- currentSum.val=0;
- numSamples=0;
- }
-
- if ( timeClipStart!=0 && histogram.Size()>=1)
- {
- timeClipStart = histogram.Peek().time+timeClipStart;
- if (histogram.PeekTail().time < timeClipStart)
- {
- histogram.Clear(_FILE_AND_LINE_);
- }
- else if (histogram.Size()>=2 && histogram.Peek().time < timeClipStart)
- {
- StatisticsHistory::TimeAndValue tav;
- do
- {
- tav = histogram.Pop();
- if (histogram.Peek().time == timeClipStart)
- {
- break;
- }
- else if (histogram.Peek().time > timeClipStart)
- {
- StatisticsHistory::TimeAndValue tav2;
- tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.Peek(), timeClipStart);
- tav2.time=timeClipStart;
- histogram.PushAtHead(tav2, 0, _FILE_AND_LINE_);
- break;
- }
- } while (histogram.Size()>=2);
- }
- }
- if ( timeClipEnd!=0 && histogram.Size()>=1)
- {
- timeClipEnd = histogram.PeekTail().time-timeClipEnd;
- if (histogram.Peek().time > timeClipEnd)
- {
- histogram.Clear(_FILE_AND_LINE_);
- }
- else if (histogram.Size()>=2 && histogram.PeekTail().time > timeClipEnd)
- {
- StatisticsHistory::TimeAndValue tav;
- do
- {
- tav = histogram.PopTail();
- if (histogram.PeekTail().time == timeClipEnd)
- {
- break;
- }
- else if (histogram.PeekTail().time < timeClipEnd)
- {
- StatisticsHistory::TimeAndValue tav2;
- tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.PeekTail(), timeClipEnd);
- tav2.time=timeClipEnd;
- histogram.Push(tav2, _FILE_AND_LINE_);
- break;
- }
- } while (histogram.Size()>=2);
- }
- }
- }
- void StatisticsHistory::TimeAndValueQueue::CullExpiredValues(Time curTime)
- {
- while (values.Size())
- {
- StatisticsHistory::TimeAndValue tav = values.Peek();
- if (curTime - tav.time > timeToTrackValues)
- {
- recentSum -= tav.val;
- recentSumOfSquares -= tav.val * tav.val;
- values.Pop();
- }
- else
- {
- break;
- }
- }
- }
- SHValueType StatisticsHistory::TimeAndValueQueue::Interpolate(StatisticsHistory::TimeAndValue t1, StatisticsHistory::TimeAndValue t2, Time time)
- {
- if (t2.time==t1.time)
- return (t1.val + t2.val) / 2;
- // if (t2.time > t1.time)
- // {
- SHValueType slope = (t2.val - t1.val) / ((SHValueType) t2.time - (SHValueType) t1.time);
- return t1.val + slope * ((SHValueType) time - (SHValueType) t1.time);
- // }
- // else
- // {
- // SHValueType slope = (t1.val - t2.val) / (SHValueType) (t1.time - t2.time);
- // return t2.val + slope * (SHValueType) (time - t2.time);
- // }
- }
- void StatisticsHistory::TimeAndValueQueue::Clear(void)
- {
- recentSum = 0;
- recentSumOfSquares = 0;
- longTermSum = 0;
- longTermCount = 0;
- longTermLowest = SH_TYPE_MAX;
- longTermHighest = -SH_TYPE_MAX;
- values.Clear(_FILE_AND_LINE_);
- }
- StatisticsHistory::TimeAndValueQueue& StatisticsHistory::TimeAndValueQueue::operator = ( const TimeAndValueQueue& input )
- {
- values=input.values;
- timeToTrackValues=input.timeToTrackValues;
- key=input.key;
- recentSum=input.recentSum;
- recentSumOfSquares=input.recentSumOfSquares;
- longTermSum=input.longTermSum;
- longTermCount=input.longTermCount;
- longTermLowest=input.longTermLowest;
- longTermHighest=input.longTermHighest;
- return *this;
- }
- StatisticsHistory::TrackedObject::TrackedObject() {}
- StatisticsHistory::TrackedObject::~TrackedObject()
- {
- DataStructures::List<StatisticsHistory::TimeAndValueQueue*> itemList;
- DataStructures::List<RakString> keyList;
- for (unsigned int idx=0; idx < itemList.Size(); idx++)
- RakNet::OP_DELETE(itemList[idx], _FILE_AND_LINE_);
- }
- unsigned int StatisticsHistory::GetObjectIndex(uint64_t objectId) const
- {
- bool objectExists;
- unsigned int idx = objects.GetIndexFromKey(objectId, &objectExists);
- if (objectExists)
- return idx;
- return (unsigned int) -1;
- }
- StatisticsHistoryPlugin::StatisticsHistoryPlugin()
- {
- addNewConnections = true;
- removeLostConnections = true;
- newConnectionsObjectType = 0;
- }
- StatisticsHistoryPlugin::~StatisticsHistoryPlugin()
- {
- }
- void StatisticsHistoryPlugin::SetTrackConnections(bool _addNewConnections, int _newConnectionsObjectType, bool _removeLostConnections)
- {
- addNewConnections = _addNewConnections;
- removeLostConnections = _removeLostConnections;
- newConnectionsObjectType = _newConnectionsObjectType;
- }
- void StatisticsHistoryPlugin::Update(void)
- {
- DataStructures::List<SystemAddress> addresses;
- DataStructures::List<RakNetGUID> guids;
- DataStructures::List<RakNetStatistics> stats;
- rakPeerInterface->GetStatisticsList(addresses, guids, stats);
- Time curTime = GetTime();
- for (unsigned int idx = 0; idx < guids.Size(); idx++)
- {
- unsigned int objectIndex = statistics.GetObjectIndex(guids[idx].g);
- if (objectIndex!=(unsigned int)-1)
- {
- statistics.AddValueByIndex(objectIndex,
- "RN_ACTUAL_BYTES_SENT",
- (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_SENT],
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_USER_MESSAGE_BYTES_RESENT",
- (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RESENT],
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_ACTUAL_BYTES_RECEIVED",
- (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_RECEIVED],
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_USER_MESSAGE_BYTES_PUSHED",
- (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_PUSHED],
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_USER_MESSAGE_BYTES_RECEIVED_PROCESSED",
- (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RECEIVED_PROCESSED],
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_lastPing",
- (SHValueType) rakPeerInterface->GetLastPing(guids[idx]),
- curTime, false);
- statistics.AddValueByIndex(objectIndex,
- "RN_bytesInResendBuffer",
- (SHValueType) stats[idx].bytesInResendBuffer,
- curTime, false);
-
- statistics.AddValueByIndex(objectIndex,
- "RN_packetlossLastSecond",
- (SHValueType) stats[idx].packetlossLastSecond,
- curTime, false);
- }
- }
- /*
- RakNetStatistics rns;
- DataStructures::List<SystemAddress> addresses;
- DataStructures::List<RakNetGUID> guids;
- rakPeerInterface->GetSystemList(addresses, guids);
- for (unsigned int idx = 0; idx < guids.Size(); idx++)
- {
- rakPeerInterface->GetStatistics(remoteSystems[idx], &rns);
- statistics.AddValue();
- bool AddValue(uint64_t objectId, RakString key, SHValueType val, Time curTime);
- }
- */
- }
- /*
- void StatisticsHistoryPlugin::OnDirectSocketSend(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress)
- {
- // Would have to use GetGuidFromSystemAddress for every send
- }
- void StatisticsHistoryPlugin::OnDirectSocketReceive(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress)
- {
- }
- */
- void StatisticsHistoryPlugin::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
- {
- (void) lostConnectionReason;
- (void) systemAddress;
- if (removeLostConnections)
- {
- statistics.RemoveObject(rakNetGUID.g, 0);
- }
- }
- void StatisticsHistoryPlugin::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
- {
- (void) systemAddress;
- (void) isIncoming;
- if (addNewConnections)
- {
- statistics.AddObject(StatisticsHistory::TrackedObjectData(rakNetGUID.g, newConnectionsObjectType, 0));
- }
- }
- // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- #endif // _RAKNET_SUPPORT_StatisticsHistory==1
|