Statistics.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/UnitTest/TestTypes.h>
  9. #include <AzCore/UnitTest/UnitTest.h>
  10. #include <AzTest/AzTest.h>
  11. #include <AzCore/Math/Crc.h>
  12. #include <AzCore/std/string/string.h>
  13. #include <AzCore/Statistics/StatisticsManager.h>
  14. using namespace AZ;
  15. using namespace Debug;
  16. namespace UnitTest
  17. {
  18. class StatisticsTest
  19. : public LeakDetectionFixture
  20. {
  21. public:
  22. StatisticsTest()
  23. {
  24. }
  25. void SetUp() override
  26. {
  27. LeakDetectionFixture::SetUp();
  28. m_dataSamples = AZStd::make_unique<AZStd::vector<u32>>();
  29. const u32 numSamples = 100;
  30. m_dataSamples->set_capacity(numSamples);
  31. for (u32 i = 0; i < numSamples; ++i)
  32. {
  33. m_dataSamples->push_back(i);
  34. }
  35. }
  36. ~StatisticsTest() override
  37. {
  38. }
  39. void TearDown() override
  40. {
  41. // clearing up memory
  42. m_dataSamples = nullptr;
  43. LeakDetectionFixture::TearDown();
  44. }
  45. protected:
  46. AZStd::unique_ptr<AZStd::vector<u32>> m_dataSamples;
  47. }; //class StatisticsTest
  48. TEST_F(StatisticsTest, RunningStatistic_ProcessAnArrayOfNumbers_GetExpectedStatisticalData)
  49. {
  50. Statistics::RunningStatistic runningStat;
  51. ASSERT_TRUE(m_dataSamples.get() != nullptr);
  52. const AZStd::vector<u32>& dataSamples = *m_dataSamples;
  53. for (u32 sample : dataSamples)
  54. {
  55. runningStat.PushSample(sample);
  56. }
  57. EXPECT_EQ(runningStat.GetNumSamples(), dataSamples.size());
  58. EXPECT_EQ(runningStat.GetMostRecentSample(), dataSamples.back());
  59. EXPECT_EQ(runningStat.GetMinimum(), dataSamples[0]);
  60. EXPECT_EQ(runningStat.GetMaximum(), dataSamples.back());
  61. EXPECT_NEAR(runningStat.GetAverage(), 49.5, 0.001);
  62. EXPECT_NEAR(runningStat.GetVariance(), 841.666, 0.001);
  63. EXPECT_NEAR(runningStat.GetStdev(), 29.011, 0.001);
  64. EXPECT_NEAR(runningStat.GetVariance(Statistics::VarianceType::P), 833.25, 0.001);
  65. EXPECT_NEAR(runningStat.GetStdev(Statistics::VarianceType::P), 28.866, 0.001);
  66. //Reset the stat object.
  67. runningStat.Reset();
  68. EXPECT_EQ(runningStat.GetNumSamples(), 0);
  69. EXPECT_EQ(runningStat.GetAverage(), 0.0);
  70. EXPECT_EQ(runningStat.GetStdev(), 0.0);
  71. }
  72. TEST_F(StatisticsTest, StatisticsManager_AddAndRemoveStatisticistics_CollectionIntegrityIsCorrect)
  73. {
  74. Statistics::StatisticsManager<> statsManager;
  75. AZStd::string statName0("stat0");
  76. AZStd::string statName1("stat1");
  77. AZStd::string statName2("stat2");
  78. AZStd::string statName3("stat3");
  79. EXPECT_TRUE(statsManager.AddStatistic(statName0, statName0, ""));
  80. EXPECT_TRUE(statsManager.AddStatistic(statName1, statName1, ""));
  81. EXPECT_TRUE(statsManager.AddStatistic(statName2, statName2, ""));
  82. EXPECT_TRUE(statsManager.AddStatistic(statName3, statName3, ""));
  83. //Validate the number of running statistics object we have so far.
  84. {
  85. AZStd::vector<Statistics::NamedRunningStatistic*> allStats;
  86. statsManager.GetAllStatistics(allStats);
  87. EXPECT_TRUE(allStats.size() == 4);
  88. }
  89. //Try to add an Stat that already exist. expect to fail.
  90. EXPECT_EQ(statsManager.AddStatistic(statName1), nullptr);
  91. //Remove stat1.
  92. statsManager.RemoveStatistic(statName1);
  93. //Validate the number of running statistics object we have so far.
  94. {
  95. AZStd::vector<Statistics::NamedRunningStatistic*> allStats;
  96. statsManager.GetAllStatistics(allStats);
  97. EXPECT_TRUE(allStats.size() == 3);
  98. }
  99. //Add stat1 again, expect to pass.
  100. EXPECT_TRUE(statsManager.AddStatistic(statName1));
  101. //Get a pointer to stat2.
  102. Statistics::NamedRunningStatistic* stat2 = statsManager.GetStatistic(statName2);
  103. ASSERT_TRUE(stat2 != nullptr);
  104. EXPECT_EQ(stat2->GetName(), statName2);
  105. }
  106. TEST_F(StatisticsTest, StatisticsManager_DistributeSamplesAcrossStatistics_StatisticsAreCorrect)
  107. {
  108. Statistics::StatisticsManager<> statsManager;
  109. AZStd::string statName0("stat0");
  110. AZStd::string statName1("stat1");
  111. AZStd::string statName2("stat2");
  112. AZStd::string statName3("stat3");
  113. EXPECT_TRUE(statsManager.AddStatistic(statName3));
  114. EXPECT_TRUE(statsManager.AddStatistic(statName0));
  115. EXPECT_TRUE(statsManager.AddStatistic(statName2));
  116. EXPECT_TRUE(statsManager.AddStatistic(statName1));
  117. //Distribute the 100 samples of data evenly across the 4 running statistics.
  118. ASSERT_TRUE(m_dataSamples.get() != nullptr);
  119. const AZStd::vector<u32>& dataSamples = *m_dataSamples;
  120. const size_t numSamples = dataSamples.size();
  121. const size_t numSamplesPerStat = numSamples / 4;
  122. size_t sampleIndex = 0;
  123. size_t nextStopIndex = numSamplesPerStat;
  124. while (sampleIndex < nextStopIndex)
  125. {
  126. statsManager.PushSampleForStatistic(statName0, dataSamples[sampleIndex]);
  127. sampleIndex++;
  128. }
  129. nextStopIndex += numSamplesPerStat;
  130. while (sampleIndex < nextStopIndex)
  131. {
  132. statsManager.PushSampleForStatistic(statName1, dataSamples[sampleIndex]);
  133. sampleIndex++;
  134. }
  135. nextStopIndex += numSamplesPerStat;
  136. while (sampleIndex < nextStopIndex)
  137. {
  138. statsManager.PushSampleForStatistic(statName2, dataSamples[sampleIndex]);
  139. sampleIndex++;
  140. }
  141. nextStopIndex += numSamplesPerStat;
  142. while (sampleIndex < nextStopIndex)
  143. {
  144. statsManager.PushSampleForStatistic(statName3, dataSamples[sampleIndex]);
  145. sampleIndex++;
  146. }
  147. EXPECT_NEAR(statsManager.GetStatistic(statName0)->GetAverage(), 12.0, 0.001);
  148. EXPECT_NEAR(statsManager.GetStatistic(statName1)->GetAverage(), 37.0, 0.001);
  149. EXPECT_NEAR(statsManager.GetStatistic(statName2)->GetAverage(), 62.0, 0.001);
  150. EXPECT_NEAR(statsManager.GetStatistic(statName3)->GetAverage(), 87.0, 0.001);
  151. EXPECT_NEAR(statsManager.GetStatistic(statName0)->GetStdev(), 7.359, 0.001);
  152. EXPECT_NEAR(statsManager.GetStatistic(statName1)->GetStdev(), 7.359, 0.001);
  153. EXPECT_NEAR(statsManager.GetStatistic(statName2)->GetStdev(), 7.359, 0.001);
  154. EXPECT_NEAR(statsManager.GetStatistic(statName3)->GetStdev(), 7.359, 0.001);
  155. //Reset one of the stats.
  156. statsManager.ResetStatistic(statName2);
  157. EXPECT_EQ(statsManager.GetStatistic(statName2)->GetAverage(), 0.0);
  158. //Reset all of the stats.
  159. statsManager.ResetAllStatistics();
  160. EXPECT_EQ(statsManager.GetStatistic(statName0)->GetNumSamples(), 0);
  161. EXPECT_EQ(statsManager.GetStatistic(statName1)->GetNumSamples(), 0);
  162. EXPECT_EQ(statsManager.GetStatistic(statName2)->GetNumSamples(), 0);
  163. EXPECT_EQ(statsManager.GetStatistic(statName3)->GetNumSamples(), 0);
  164. }
  165. TEST_F(StatisticsTest, StatisticsManagerCrc32_DistributeSamplesAcrossStatistics_StatisticsAreCorrect)
  166. {
  167. Statistics::StatisticsManager<AZ::Crc32> statsManager;
  168. AZ::Crc32 statName0 = AZ_CRC_CE("stat0");
  169. AZ::Crc32 statName1 = AZ_CRC_CE("stat1");
  170. AZ::Crc32 statName2 = AZ_CRC_CE("stat2");
  171. AZ::Crc32 statName3 = AZ_CRC_CE("stat3");
  172. EXPECT_TRUE(statsManager.AddStatistic(statName3) != nullptr);
  173. EXPECT_TRUE(statsManager.AddStatistic(statName0) != nullptr);
  174. EXPECT_TRUE(statsManager.AddStatistic(statName2) != nullptr);
  175. EXPECT_TRUE(statsManager.AddStatistic(statName1) != nullptr);
  176. EXPECT_TRUE(statsManager.GetStatistic(statName3) != nullptr);
  177. EXPECT_TRUE(statsManager.GetStatistic(statName0) != nullptr);
  178. EXPECT_TRUE(statsManager.GetStatistic(statName1) != nullptr);
  179. EXPECT_TRUE(statsManager.GetStatistic(statName2) != nullptr);
  180. //Distribute the 100 samples of data evenly across the 4 running statistics.
  181. ASSERT_TRUE(m_dataSamples.get() != nullptr);
  182. const AZStd::vector<u32>& dataSamples = *m_dataSamples;
  183. const size_t numSamples = dataSamples.size();
  184. const size_t numSamplesPerStat = numSamples / 4;
  185. size_t sampleIndex = 0;
  186. size_t nextStopIndex = numSamplesPerStat;
  187. while (sampleIndex < nextStopIndex)
  188. {
  189. statsManager.PushSampleForStatistic(statName0, dataSamples[sampleIndex]);
  190. sampleIndex++;
  191. }
  192. nextStopIndex += numSamplesPerStat;
  193. while (sampleIndex < nextStopIndex)
  194. {
  195. statsManager.PushSampleForStatistic(statName1, dataSamples[sampleIndex]);
  196. sampleIndex++;
  197. }
  198. nextStopIndex += numSamplesPerStat;
  199. while (sampleIndex < nextStopIndex)
  200. {
  201. statsManager.PushSampleForStatistic(statName2, dataSamples[sampleIndex]);
  202. sampleIndex++;
  203. }
  204. nextStopIndex += numSamplesPerStat;
  205. while (sampleIndex < nextStopIndex)
  206. {
  207. statsManager.PushSampleForStatistic(statName3, dataSamples[sampleIndex]);
  208. sampleIndex++;
  209. }
  210. EXPECT_NEAR(statsManager.GetStatistic(statName0)->GetAverage(), 12.0, 0.001);
  211. EXPECT_NEAR(statsManager.GetStatistic(statName1)->GetAverage(), 37.0, 0.001);
  212. EXPECT_NEAR(statsManager.GetStatistic(statName2)->GetAverage(), 62.0, 0.001);
  213. EXPECT_NEAR(statsManager.GetStatistic(statName3)->GetAverage(), 87.0, 0.001);
  214. EXPECT_NEAR(statsManager.GetStatistic(statName0)->GetStdev(), 7.359, 0.001);
  215. EXPECT_NEAR(statsManager.GetStatistic(statName1)->GetStdev(), 7.359, 0.001);
  216. EXPECT_NEAR(statsManager.GetStatistic(statName2)->GetStdev(), 7.359, 0.001);
  217. EXPECT_NEAR(statsManager.GetStatistic(statName3)->GetStdev(), 7.359, 0.001);
  218. //Reset one of the stats.
  219. statsManager.ResetStatistic(statName2);
  220. EXPECT_EQ(statsManager.GetStatistic(statName2)->GetAverage(), 0.0);
  221. //Reset all of the stats.
  222. statsManager.ResetAllStatistics();
  223. EXPECT_EQ(statsManager.GetStatistic(statName0)->GetNumSamples(), 0);
  224. EXPECT_EQ(statsManager.GetStatistic(statName1)->GetNumSamples(), 0);
  225. EXPECT_EQ(statsManager.GetStatistic(statName2)->GetNumSamples(), 0);
  226. EXPECT_EQ(statsManager.GetStatistic(statName3)->GetNumSamples(), 0);
  227. }
  228. }//namespace UnitTest