StatisticsHistory.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "NativeFeatureIncludes.h"
  11. #if _RAKNET_SUPPORT_StatisticsHistory==1
  12. #include "StatisticsHistory.h"
  13. #include "GetTime.h"
  14. #include "RakNetStatistics.h"
  15. #include "RakPeerInterface.h"
  16. using namespace RakNet;
  17. STATIC_FACTORY_DEFINITIONS(StatisticsHistory,StatisticsHistory);
  18. STATIC_FACTORY_DEFINITIONS(StatisticsHistoryPlugin,StatisticsHistoryPlugin);
  19. int StatisticsHistory::TrackedObjectComp( const uint64_t &key, StatisticsHistory::TrackedObject* const &data )
  20. {
  21. if (key < data->trackedObjectData.objectId)
  22. return -1;
  23. if (key == data->trackedObjectData.objectId)
  24. return 0;
  25. return 1;
  26. }
  27. int TimeAndValueQueueCompAsc( StatisticsHistory::TimeAndValueQueue* const &key, StatisticsHistory::TimeAndValueQueue* const &data )
  28. {
  29. if (key->sortValue < data->sortValue)
  30. return -1;
  31. if (key->sortValue > data->sortValue)
  32. return 1;
  33. if (key->key < data->key)
  34. return -1;
  35. if (key->key > data->key)
  36. return 1;
  37. return 0;
  38. }
  39. int TimeAndValueQueueCompDesc( StatisticsHistory::TimeAndValueQueue* const &key, StatisticsHistory::TimeAndValueQueue* const &data )
  40. {
  41. if (key->sortValue > data->sortValue)
  42. return -1;
  43. if (key->sortValue < data->sortValue)
  44. return 1;
  45. if (key->key > data->key)
  46. return -1;
  47. if (key->key < data->key)
  48. return 1;
  49. return 0;
  50. }
  51. StatisticsHistory::TrackedObjectData::TrackedObjectData() {}
  52. StatisticsHistory::TrackedObjectData::TrackedObjectData(uint64_t _objectId, int _objectType, void *_userData)
  53. {
  54. objectId=_objectId;
  55. objectType=_objectType;
  56. userData=_userData;
  57. }
  58. StatisticsHistory::StatisticsHistory() {timeToTrack = 30000;}
  59. StatisticsHistory::~StatisticsHistory()
  60. {
  61. Clear();
  62. }
  63. void StatisticsHistory::SetDefaultTimeToTrack(Time defaultTimeToTrack) {timeToTrack = defaultTimeToTrack;}
  64. Time StatisticsHistory::GetDefaultTimeToTrack(void) const {return timeToTrack;}
  65. bool StatisticsHistory::AddObject(TrackedObjectData tod)
  66. {
  67. bool objectExists;
  68. unsigned int idx = objects.GetIndexFromKey(tod.objectId, &objectExists);
  69. if (objectExists)
  70. return false;
  71. TrackedObject *to = RakNet::OP_NEW<TrackedObject>(_FILE_AND_LINE_);
  72. to->trackedObjectData=tod;
  73. objects.InsertAtIndex(to,idx,_FILE_AND_LINE_);
  74. return true;
  75. }
  76. bool StatisticsHistory::RemoveObject(uint64_t objectId, void **userData)
  77. {
  78. unsigned int idx = GetObjectIndex(objectId);
  79. if (idx == (unsigned int) -1)
  80. return false;
  81. if (userData)
  82. *userData = objects[idx]->trackedObjectData.userData;
  83. RemoveObjectAtIndex(idx);
  84. return true;
  85. }
  86. void StatisticsHistory::RemoveObjectAtIndex(unsigned int index)
  87. {
  88. TrackedObject *to = objects[index];
  89. objects.RemoveAtIndex(index);
  90. RakNet::OP_DELETE(to, _FILE_AND_LINE_);
  91. }
  92. void StatisticsHistory::Clear(void)
  93. {
  94. for (unsigned int idx=0; idx < objects.Size(); idx++)
  95. {
  96. RakNet::OP_DELETE(objects[idx], _FILE_AND_LINE_);
  97. }
  98. objects.Clear(false, _FILE_AND_LINE_);
  99. }
  100. unsigned int StatisticsHistory::GetObjectCount(void) const {return objects.Size();}
  101. StatisticsHistory::TrackedObjectData * StatisticsHistory::GetObjectAtIndex(unsigned int index) const {return &objects[index]->trackedObjectData;}
  102. bool StatisticsHistory::AddValueByObjectID(uint64_t objectId, RakString key, SHValueType val, Time curTime, bool combineEqualTimes)
  103. {
  104. unsigned int idx = GetObjectIndex(objectId);
  105. if (idx == (unsigned int) -1)
  106. return false;
  107. AddValueByIndex(idx, key, val, curTime, combineEqualTimes);
  108. return true;
  109. }
  110. void StatisticsHistory::AddValueByIndex(unsigned int index, RakString key, SHValueType val, Time curTime, bool combineEqualTimes)
  111. {
  112. TimeAndValueQueue *queue;
  113. TrackedObject *to = objects[index];
  114. DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
  115. if (hi.IsInvalid())
  116. {
  117. queue = RakNet::OP_NEW<TimeAndValueQueue>(_FILE_AND_LINE_);
  118. queue->key=key;
  119. queue->timeToTrackValues = timeToTrack;
  120. to->dataQueues.Push(key, queue, _FILE_AND_LINE_);
  121. }
  122. else
  123. {
  124. queue = to->dataQueues.ItemAtIndex(hi);
  125. }
  126. TimeAndValue tav;
  127. if (combineEqualTimes==true && queue->values.Size()>0 && queue->values.PeekTail().time==curTime)
  128. {
  129. tav = queue->values.PopTail();
  130. queue->recentSum -= tav.val;
  131. queue->recentSumOfSquares -= tav.val * tav.val;
  132. queue->longTermSum -= tav.val;
  133. queue->longTermCount = queue->longTermCount - 1;
  134. }
  135. else
  136. {
  137. tav.val=0.0;
  138. tav.time=curTime;
  139. }
  140. tav.val+=val;
  141. queue->values.Push(tav, _FILE_AND_LINE_);
  142. queue->recentSum += tav.val;
  143. queue->recentSumOfSquares += tav.val * tav.val;
  144. queue->longTermSum += tav.val;
  145. queue->longTermCount = queue->longTermCount + 1;
  146. if (queue->longTermLowest > tav.val)
  147. queue->longTermLowest = tav.val;
  148. if (queue->longTermHighest < tav.val)
  149. queue->longTermHighest = tav.val;
  150. }
  151. StatisticsHistory::SHErrorCode StatisticsHistory::GetHistoryForKey(uint64_t objectId, RakString key, StatisticsHistory::TimeAndValueQueue **values, Time curTime) const
  152. {
  153. if (values == 0)
  154. return SH_INVALID_PARAMETER;
  155. unsigned int idx = GetObjectIndex(objectId);
  156. if (idx == (unsigned int) -1)
  157. return SH_UKNOWN_OBJECT;
  158. TrackedObject *to = objects[idx];
  159. DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
  160. if (hi.IsInvalid())
  161. return SH_UKNOWN_KEY;
  162. *values = to->dataQueues.ItemAtIndex(hi);
  163. (*values)->CullExpiredValues(curTime);
  164. return SH_OK;
  165. }
  166. bool StatisticsHistory::GetHistorySorted(uint64_t objectId, SHSortOperation sortType, DataStructures::List<StatisticsHistory::TimeAndValueQueue *> &values) const
  167. {
  168. unsigned int idx = GetObjectIndex(objectId);
  169. if (idx == (unsigned int) -1)
  170. return false;
  171. TrackedObject *to = objects[idx];
  172. DataStructures::List<TimeAndValueQueue*> itemList;
  173. DataStructures::List<RakString> keyList;
  174. to->dataQueues.GetAsList(itemList,keyList,_FILE_AND_LINE_);
  175. Time curTime = GetTime();
  176. DataStructures::OrderedList<TimeAndValueQueue*, TimeAndValueQueue*,TimeAndValueQueueCompAsc> sortedQueues;
  177. for (unsigned int i=0; i < itemList.Size(); i++)
  178. {
  179. TimeAndValueQueue *tavq = itemList[i];
  180. tavq->CullExpiredValues(curTime);
  181. if (sortType == SH_SORT_BY_RECENT_SUM_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_DESCENDING)
  182. tavq->sortValue = tavq->GetRecentSum();
  183. else if (sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_SUM_DESCENDING)
  184. tavq->sortValue = tavq->GetLongTermSum();
  185. else if (sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_DESCENDING)
  186. tavq->sortValue = tavq->GetRecentSumOfSquares();
  187. else if (sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING || sortType == SH_SORT_BY_RECENT_AVERAGE_DESCENDING)
  188. tavq->sortValue = tavq->GetRecentAverage();
  189. else if (sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_AVERAGE_DESCENDING)
  190. tavq->sortValue = tavq->GetLongTermAverage();
  191. else if (sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING || sortType == SH_SORT_BY_RECENT_HIGHEST_DESCENDING)
  192. tavq->sortValue = tavq->GetRecentHighest();
  193. else if (sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING || sortType == SH_SORT_BY_RECENT_LOWEST_DESCENDING)
  194. tavq->sortValue = tavq->GetRecentLowest();
  195. else if (sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_HIGHEST_DESCENDING)
  196. tavq->sortValue = tavq->GetLongTermHighest();
  197. else
  198. tavq->sortValue = tavq->GetLongTermLowest();
  199. if (
  200. sortType == SH_SORT_BY_RECENT_SUM_ASCENDING ||
  201. sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING ||
  202. sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING ||
  203. sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING ||
  204. sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING ||
  205. sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING ||
  206. sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING ||
  207. sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING ||
  208. sortType == SH_SORT_BY_LONG_TERM_LOWEST_ASCENDING)
  209. sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompAsc);
  210. else
  211. sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompDesc);
  212. }
  213. for (unsigned int i=0; i < sortedQueues.Size(); i++)
  214. values.Push(sortedQueues[i], _FILE_AND_LINE_);
  215. return true;
  216. }
  217. void StatisticsHistory::MergeAllObjectsOnKey(RakString key, TimeAndValueQueue *tavqOutput, SHDataCategory dataCategory) const
  218. {
  219. tavqOutput->Clear();
  220. Time curTime = GetTime();
  221. // Find every object with this key
  222. for (unsigned int idx=0; idx < objects.Size(); idx++)
  223. {
  224. TrackedObject *to = objects[idx];
  225. DataStructures::HashIndex hi = to->dataQueues.GetIndexOf(key);
  226. if (hi.IsInvalid()==false)
  227. {
  228. TimeAndValueQueue *tavqInput = to->dataQueues.ItemAtIndex(hi);
  229. tavqInput->CullExpiredValues(curTime);
  230. TimeAndValueQueue::MergeSets(tavqOutput, dataCategory, tavqInput, dataCategory, tavqOutput);
  231. }
  232. }
  233. }
  234. void StatisticsHistory::GetUniqueKeyList(DataStructures::List<RakString> &keys)
  235. {
  236. keys.Clear(true, _FILE_AND_LINE_);
  237. for (unsigned int idx=0; idx < objects.Size(); idx++)
  238. {
  239. TrackedObject *to = objects[idx];
  240. DataStructures::List<TimeAndValueQueue*> itemList;
  241. DataStructures::List<RakNet::RakString> keyList;
  242. to->dataQueues.GetAsList(itemList, keyList, _FILE_AND_LINE_);
  243. for (unsigned int k=0; k < keyList.Size(); k++)
  244. {
  245. bool hasKey=false;
  246. for (unsigned int j=0; j < keys.Size(); j++)
  247. {
  248. if (keys[j]==keyList[k])
  249. {
  250. hasKey=true;
  251. break;
  252. }
  253. }
  254. if (hasKey==false)
  255. keys.Push(keyList[k], _FILE_AND_LINE_);
  256. }
  257. }
  258. }
  259. StatisticsHistory::TimeAndValueQueue::TimeAndValueQueue()
  260. {
  261. Clear();
  262. }
  263. StatisticsHistory::TimeAndValueQueue::~TimeAndValueQueue(){}
  264. void StatisticsHistory::TimeAndValueQueue::SetTimeToTrackValues(Time t)
  265. {
  266. timeToTrackValues = t;
  267. }
  268. Time StatisticsHistory::TimeAndValueQueue::GetTimeToTrackValues(void) const {return timeToTrackValues;}
  269. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentSum(void) const {return recentSum;}
  270. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentSumOfSquares(void) const {return recentSumOfSquares;}
  271. SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermSum(void) const {return longTermSum;}
  272. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentAverage(void) const
  273. {
  274. if (values.Size() > 0)
  275. return recentSum / (SHValueType) values.Size();
  276. else
  277. return 0;
  278. }
  279. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentLowest(void) const
  280. {
  281. SHValueType out = SH_TYPE_MAX;
  282. for (unsigned int idx=0; idx < values.Size(); idx++)
  283. {
  284. if (values[idx].val < out)
  285. out = values[idx].val;
  286. }
  287. return out;
  288. }
  289. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentHighest(void) const
  290. {
  291. SHValueType out = -SH_TYPE_MAX;
  292. for (unsigned int idx=0; idx < values.Size(); idx++)
  293. {
  294. if (values[idx].val > out)
  295. out = values[idx].val;
  296. }
  297. return out;
  298. }
  299. SHValueType StatisticsHistory::TimeAndValueQueue::GetRecentStandardDeviation(void) const
  300. {
  301. if (values.Size()==0)
  302. return 0;
  303. SHValueType recentMean= GetRecentAverage();
  304. SHValueType squareOfMean = recentMean * recentMean;
  305. SHValueType meanOfSquares = GetRecentSumOfSquares() / (SHValueType) values.Size();
  306. return meanOfSquares - squareOfMean;
  307. }
  308. SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermAverage(void) const
  309. {
  310. if (longTermCount == 0)
  311. return 0;
  312. return longTermSum / longTermCount;
  313. }
  314. SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermLowest(void) const {return longTermLowest;}
  315. SHValueType StatisticsHistory::TimeAndValueQueue::GetLongTermHighest(void) const {return longTermHighest;}
  316. Time StatisticsHistory::TimeAndValueQueue::GetTimeRange(void) const
  317. {
  318. if (values.Size()<2)
  319. return 0;
  320. return values[values.Size()-1].time - values[0].time;
  321. }
  322. SHValueType StatisticsHistory::TimeAndValueQueue::GetSumSinceTime(Time t) const
  323. {
  324. SHValueType sum = 0;
  325. for (int i=values.Size(); i > 0; --i)
  326. {
  327. if (values[i-1].time>=t)
  328. sum+=values[i-1].val;
  329. }
  330. return sum;
  331. }
  332. void StatisticsHistory::TimeAndValueQueue::MergeSets( const TimeAndValueQueue *lhs, SHDataCategory lhsDataCategory, const TimeAndValueQueue *rhs, SHDataCategory rhsDataCategory, TimeAndValueQueue *output )
  333. {
  334. // Two ways to merge:
  335. // 1. Treat rhs as just more data points.
  336. // 1A. Sums are just added. If two values have the same time, just put in queue twice
  337. // 1B. longTermLowest and longTermHighest are the lowest and highest of the two sets
  338. //
  339. // 2. Add by time. If time for the other set is missing, calculate slope to extrapolate
  340. // 2A. Have to recalculate recentSum, recentSumOfSquares.
  341. // 2B. longTermSum, longTermCount, longTermLowest, longTermHighest are unknown
  342. if (lhs!=output)
  343. {
  344. output->key = lhs->key;
  345. output->timeToTrackValues = lhs->timeToTrackValues;
  346. }
  347. else
  348. {
  349. output->key = rhs->key;
  350. output->timeToTrackValues = rhs->timeToTrackValues;
  351. }
  352. unsigned int lhsIndex, rhsIndex;
  353. lhsIndex=0;
  354. rhsIndex=0;
  355. // I use local valuesOutput in case lhs==output || rhs==output
  356. DataStructures::Queue<TimeAndValue> valuesOutput;
  357. if (lhsDataCategory==StatisticsHistory::DC_DISCRETE && rhsDataCategory==StatisticsHistory::DC_DISCRETE)
  358. {
  359. while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
  360. {
  361. if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
  362. {
  363. valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
  364. rhsIndex++;
  365. }
  366. else if (rhs->values[rhsIndex].time > lhs->values[lhsIndex].time)
  367. {
  368. valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
  369. lhsIndex++;
  370. }
  371. else
  372. {
  373. valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
  374. rhsIndex++;
  375. valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
  376. lhsIndex++;
  377. }
  378. }
  379. while (rhsIndex < rhs->values.Size())
  380. {
  381. valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
  382. rhsIndex++;
  383. }
  384. while (lhsIndex < lhs->values.Size())
  385. {
  386. valuesOutput.Push(lhs->values[lhsIndex], _FILE_AND_LINE_ );
  387. lhsIndex++;
  388. }
  389. output->recentSum = lhs->recentSum + rhs->recentSum;
  390. output->recentSumOfSquares = lhs->recentSumOfSquares + rhs->recentSumOfSquares;
  391. output->longTermSum = lhs->longTermSum + rhs->longTermSum;
  392. output->longTermCount = lhs->longTermCount + rhs->longTermCount;
  393. if (lhs->longTermLowest < rhs->longTermLowest)
  394. output->longTermLowest = lhs->longTermLowest;
  395. else
  396. output->longTermLowest = rhs->longTermLowest;
  397. if (lhs->longTermHighest > rhs->longTermHighest)
  398. output->longTermHighest = lhs->longTermHighest;
  399. else
  400. output->longTermHighest = rhs->longTermHighest;
  401. }
  402. else
  403. {
  404. TimeAndValue lastTimeAndValueLhs, lastTimeAndValueRhs;
  405. lastTimeAndValueLhs.time=0;
  406. lastTimeAndValueLhs.val=0;
  407. lastTimeAndValueRhs.time=0;
  408. lastTimeAndValueRhs.val=0;
  409. SHValueType lastSlopeLhs=0;
  410. SHValueType lastSlopeRhs=0;
  411. Time timeSinceOppositeValue;
  412. TimeAndValue newTimeAndValue;
  413. while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
  414. {
  415. if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
  416. {
  417. timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
  418. newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
  419. newTimeAndValue.time = rhs->values[rhsIndex].time;
  420. lastTimeAndValueRhs = rhs->values[rhsIndex];
  421. if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
  422. lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
  423. rhsIndex++;
  424. }
  425. else if (lhs->values[lhsIndex].time < rhs->values[rhsIndex].time)
  426. {
  427. timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
  428. newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
  429. newTimeAndValue.time = lhs->values[lhsIndex].time;
  430. lastTimeAndValueLhs = lhs->values[lhsIndex];
  431. if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
  432. lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
  433. lhsIndex++;
  434. }
  435. else
  436. {
  437. newTimeAndValue.val = lhs->values[lhsIndex].val + rhs->values[rhsIndex].val;
  438. newTimeAndValue.time = lhs->values[lhsIndex].time;
  439. lastTimeAndValueRhs = rhs->values[rhsIndex];
  440. lastTimeAndValueLhs = lhs->values[lhsIndex];
  441. if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
  442. lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
  443. if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
  444. lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
  445. lhsIndex++;
  446. rhsIndex++;
  447. }
  448. valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
  449. }
  450. while (rhsIndex < rhs->values.Size())
  451. {
  452. timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
  453. newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
  454. newTimeAndValue.time = rhs->values[rhsIndex].time;
  455. valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
  456. rhsIndex++;
  457. }
  458. while (lhsIndex < lhs->values.Size())
  459. {
  460. timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
  461. newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
  462. newTimeAndValue.time = lhs->values[lhsIndex].time;
  463. valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
  464. lhsIndex++;
  465. }
  466. output->recentSum = 0;
  467. output->recentSumOfSquares = 0;
  468. for (unsigned int i=0; i < valuesOutput.Size(); i++)
  469. {
  470. output->recentSum += valuesOutput[i].val;
  471. output->recentSumOfSquares += valuesOutput[i].val * valuesOutput[i].val;
  472. }
  473. }
  474. output->values = valuesOutput;
  475. }
  476. void StatisticsHistory::TimeAndValueQueue::ResizeSampleSet( int maxSamples, DataStructures::Queue<StatisticsHistory::TimeAndValue> &histogram, SHDataCategory dataCategory, Time timeClipStart, Time timeClipEnd )
  477. {
  478. histogram.Clear(_FILE_AND_LINE_);
  479. if (maxSamples==0)
  480. return;
  481. Time timeRange = GetTimeRange();
  482. if (timeRange==0)
  483. return;
  484. if (maxSamples==1)
  485. {
  486. StatisticsHistory::TimeAndValue tav;
  487. tav.time = timeRange;
  488. tav.val = GetRecentSum();
  489. histogram.Push(tav, _FILE_AND_LINE_);
  490. return;
  491. }
  492. Time interval = timeRange / maxSamples;
  493. if (interval==0)
  494. interval=1;
  495. unsigned int dataIndex;
  496. Time timeBoundary;
  497. StatisticsHistory::TimeAndValue currentSum;
  498. Time currentTime;
  499. SHValueType numSamples;
  500. Time endTime;
  501. numSamples=0;
  502. endTime = values[values.Size()-1].time;
  503. dataIndex=0;
  504. currentTime=values[0].time;
  505. currentSum.val=0;
  506. currentSum.time=values[0].time + interval / 2;
  507. timeBoundary = values[0].time + interval;
  508. while (timeBoundary <= endTime)
  509. {
  510. while (dataIndex < values.Size() && values[dataIndex].time <= timeBoundary)
  511. {
  512. currentSum.val += values[dataIndex].val;
  513. dataIndex++;
  514. numSamples++;
  515. }
  516. if (dataCategory==DC_CONTINUOUS)
  517. {
  518. if (dataIndex > 0 &&
  519. dataIndex < values.Size() &&
  520. values[dataIndex-1].time < timeBoundary &&
  521. values[dataIndex].time > timeBoundary)
  522. {
  523. SHValueType interpolatedValue = Interpolate(values[dataIndex-1], values[dataIndex], timeBoundary);
  524. currentSum.val+=interpolatedValue;
  525. numSamples++;
  526. }
  527. if (numSamples > 1)
  528. {
  529. currentSum.val /= numSamples;
  530. }
  531. }
  532. histogram.Push(currentSum, _FILE_AND_LINE_);
  533. currentSum.time=timeBoundary + interval / 2;
  534. timeBoundary += interval;
  535. currentSum.val=0;
  536. numSamples=0;
  537. }
  538. if ( timeClipStart!=0 && histogram.Size()>=1)
  539. {
  540. timeClipStart = histogram.Peek().time+timeClipStart;
  541. if (histogram.PeekTail().time < timeClipStart)
  542. {
  543. histogram.Clear(_FILE_AND_LINE_);
  544. }
  545. else if (histogram.Size()>=2 && histogram.Peek().time < timeClipStart)
  546. {
  547. StatisticsHistory::TimeAndValue tav;
  548. do
  549. {
  550. tav = histogram.Pop();
  551. if (histogram.Peek().time == timeClipStart)
  552. {
  553. break;
  554. }
  555. else if (histogram.Peek().time > timeClipStart)
  556. {
  557. StatisticsHistory::TimeAndValue tav2;
  558. tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.Peek(), timeClipStart);
  559. tav2.time=timeClipStart;
  560. histogram.PushAtHead(tav2, 0, _FILE_AND_LINE_);
  561. break;
  562. }
  563. } while (histogram.Size()>=2);
  564. }
  565. }
  566. if ( timeClipEnd!=0 && histogram.Size()>=1)
  567. {
  568. timeClipEnd = histogram.PeekTail().time-timeClipEnd;
  569. if (histogram.Peek().time > timeClipEnd)
  570. {
  571. histogram.Clear(_FILE_AND_LINE_);
  572. }
  573. else if (histogram.Size()>=2 && histogram.PeekTail().time > timeClipEnd)
  574. {
  575. StatisticsHistory::TimeAndValue tav;
  576. do
  577. {
  578. tav = histogram.PopTail();
  579. if (histogram.PeekTail().time == timeClipEnd)
  580. {
  581. break;
  582. }
  583. else if (histogram.PeekTail().time < timeClipEnd)
  584. {
  585. StatisticsHistory::TimeAndValue tav2;
  586. tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.PeekTail(), timeClipEnd);
  587. tav2.time=timeClipEnd;
  588. histogram.Push(tav2, _FILE_AND_LINE_);
  589. break;
  590. }
  591. } while (histogram.Size()>=2);
  592. }
  593. }
  594. }
  595. void StatisticsHistory::TimeAndValueQueue::CullExpiredValues(Time curTime)
  596. {
  597. while (values.Size())
  598. {
  599. StatisticsHistory::TimeAndValue tav = values.Peek();
  600. if (curTime - tav.time > timeToTrackValues)
  601. {
  602. recentSum -= tav.val;
  603. recentSumOfSquares -= tav.val * tav.val;
  604. values.Pop();
  605. }
  606. else
  607. {
  608. break;
  609. }
  610. }
  611. }
  612. SHValueType StatisticsHistory::TimeAndValueQueue::Interpolate(StatisticsHistory::TimeAndValue t1, StatisticsHistory::TimeAndValue t2, Time time)
  613. {
  614. if (t2.time==t1.time)
  615. return (t1.val + t2.val) / 2;
  616. // if (t2.time > t1.time)
  617. // {
  618. SHValueType slope = (t2.val - t1.val) / ((SHValueType) t2.time - (SHValueType) t1.time);
  619. return t1.val + slope * ((SHValueType) time - (SHValueType) t1.time);
  620. // }
  621. // else
  622. // {
  623. // SHValueType slope = (t1.val - t2.val) / (SHValueType) (t1.time - t2.time);
  624. // return t2.val + slope * (SHValueType) (time - t2.time);
  625. // }
  626. }
  627. void StatisticsHistory::TimeAndValueQueue::Clear(void)
  628. {
  629. recentSum = 0;
  630. recentSumOfSquares = 0;
  631. longTermSum = 0;
  632. longTermCount = 0;
  633. longTermLowest = SH_TYPE_MAX;
  634. longTermHighest = -SH_TYPE_MAX;
  635. values.Clear(_FILE_AND_LINE_);
  636. }
  637. StatisticsHistory::TimeAndValueQueue& StatisticsHistory::TimeAndValueQueue::operator = ( const TimeAndValueQueue& input )
  638. {
  639. values=input.values;
  640. timeToTrackValues=input.timeToTrackValues;
  641. key=input.key;
  642. recentSum=input.recentSum;
  643. recentSumOfSquares=input.recentSumOfSquares;
  644. longTermSum=input.longTermSum;
  645. longTermCount=input.longTermCount;
  646. longTermLowest=input.longTermLowest;
  647. longTermHighest=input.longTermHighest;
  648. return *this;
  649. }
  650. StatisticsHistory::TrackedObject::TrackedObject() {}
  651. StatisticsHistory::TrackedObject::~TrackedObject()
  652. {
  653. DataStructures::List<StatisticsHistory::TimeAndValueQueue*> itemList;
  654. DataStructures::List<RakString> keyList;
  655. for (unsigned int idx=0; idx < itemList.Size(); idx++)
  656. RakNet::OP_DELETE(itemList[idx], _FILE_AND_LINE_);
  657. }
  658. unsigned int StatisticsHistory::GetObjectIndex(uint64_t objectId) const
  659. {
  660. bool objectExists;
  661. unsigned int idx = objects.GetIndexFromKey(objectId, &objectExists);
  662. if (objectExists)
  663. return idx;
  664. return (unsigned int) -1;
  665. }
  666. StatisticsHistoryPlugin::StatisticsHistoryPlugin()
  667. {
  668. addNewConnections = true;
  669. removeLostConnections = true;
  670. newConnectionsObjectType = 0;
  671. }
  672. StatisticsHistoryPlugin::~StatisticsHistoryPlugin()
  673. {
  674. }
  675. void StatisticsHistoryPlugin::SetTrackConnections(bool _addNewConnections, int _newConnectionsObjectType, bool _removeLostConnections)
  676. {
  677. addNewConnections = _addNewConnections;
  678. removeLostConnections = _removeLostConnections;
  679. newConnectionsObjectType = _newConnectionsObjectType;
  680. }
  681. void StatisticsHistoryPlugin::Update(void)
  682. {
  683. DataStructures::List<SystemAddress> addresses;
  684. DataStructures::List<RakNetGUID> guids;
  685. DataStructures::List<RakNetStatistics> stats;
  686. rakPeerInterface->GetStatisticsList(addresses, guids, stats);
  687. Time curTime = GetTime();
  688. for (unsigned int idx = 0; idx < guids.Size(); idx++)
  689. {
  690. unsigned int objectIndex = statistics.GetObjectIndex(guids[idx].g);
  691. if (objectIndex!=(unsigned int)-1)
  692. {
  693. statistics.AddValueByIndex(objectIndex,
  694. "RN_ACTUAL_BYTES_SENT",
  695. (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_SENT],
  696. curTime, false);
  697. statistics.AddValueByIndex(objectIndex,
  698. "RN_USER_MESSAGE_BYTES_RESENT",
  699. (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RESENT],
  700. curTime, false);
  701. statistics.AddValueByIndex(objectIndex,
  702. "RN_ACTUAL_BYTES_RECEIVED",
  703. (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_RECEIVED],
  704. curTime, false);
  705. statistics.AddValueByIndex(objectIndex,
  706. "RN_USER_MESSAGE_BYTES_PUSHED",
  707. (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_PUSHED],
  708. curTime, false);
  709. statistics.AddValueByIndex(objectIndex,
  710. "RN_USER_MESSAGE_BYTES_RECEIVED_PROCESSED",
  711. (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RECEIVED_PROCESSED],
  712. curTime, false);
  713. statistics.AddValueByIndex(objectIndex,
  714. "RN_lastPing",
  715. (SHValueType) rakPeerInterface->GetLastPing(guids[idx]),
  716. curTime, false);
  717. statistics.AddValueByIndex(objectIndex,
  718. "RN_bytesInResendBuffer",
  719. (SHValueType) stats[idx].bytesInResendBuffer,
  720. curTime, false);
  721. statistics.AddValueByIndex(objectIndex,
  722. "RN_packetlossLastSecond",
  723. (SHValueType) stats[idx].packetlossLastSecond,
  724. curTime, false);
  725. }
  726. }
  727. /*
  728. RakNetStatistics rns;
  729. DataStructures::List<SystemAddress> addresses;
  730. DataStructures::List<RakNetGUID> guids;
  731. rakPeerInterface->GetSystemList(addresses, guids);
  732. for (unsigned int idx = 0; idx < guids.Size(); idx++)
  733. {
  734. rakPeerInterface->GetStatistics(remoteSystems[idx], &rns);
  735. statistics.AddValue();
  736. bool AddValue(uint64_t objectId, RakString key, SHValueType val, Time curTime);
  737. }
  738. */
  739. }
  740. /*
  741. void StatisticsHistoryPlugin::OnDirectSocketSend(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress)
  742. {
  743. // Would have to use GetGuidFromSystemAddress for every send
  744. }
  745. void StatisticsHistoryPlugin::OnDirectSocketReceive(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress)
  746. {
  747. }
  748. */
  749. void StatisticsHistoryPlugin::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  750. {
  751. (void) lostConnectionReason;
  752. (void) systemAddress;
  753. if (removeLostConnections)
  754. {
  755. statistics.RemoveObject(rakNetGUID.g, 0);
  756. }
  757. }
  758. void StatisticsHistoryPlugin::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
  759. {
  760. (void) systemAddress;
  761. (void) isIncoming;
  762. if (addNewConnections)
  763. {
  764. statistics.AddObject(StatisticsHistory::TrackedObjectData(rakNetGUID.g, newConnectionsObjectType, 0));
  765. }
  766. }
  767. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  768. #endif // _RAKNET_SUPPORT_StatisticsHistory==1
粤ICP备19079148号