PerfTestThreadAtomic.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. ////////////////////////////////////////////////////////////////////////
  2. // PerfTestThreadAtomic.cpp
  3. //
  4. // Copyright (c) 2014, Electronic Arts Inc. All rights reserved.
  5. ////////////////////////////////////////////////////////////////////////
  6. #include "benchmarkenvironment/results.h"
  7. #include "benchmarkenvironment/statistics.h"
  8. #include "benchmarkenvironment/timer.h"
  9. #include "eathread/eathread_atomic.h"
  10. #include "eathread/eathread_thread.h"
  11. #include "EATest/EATest.h"
  12. #include "PerfTestThread.h"
  13. using namespace EA::Thread;
  14. #if EA_THREADS_AVAILABLE
  15. // ------------------------------------------------------------------------
  16. // Each thread that is involved in these tests will get its own independent timer, and a
  17. // shared atomic variable. With each thread doing its own timing, we should be able to
  18. // remove scheduling noise to the greatest degree possible.
  19. //
  20. struct AtomicAndTimer
  21. {
  22. static AtomicInt32 mAtomicInteger;
  23. benchmarkenvironment::Timer mLocalTimer;
  24. };
  25. AtomicInt32 AtomicAndTimer::mAtomicInteger = 0;
  26. // ------------------------------------------------------------------------
  27. //
  28. static intptr_t AtomicIntMath(void* pWorkStructure)
  29. {
  30. AtomicAndTimer& at = *static_cast<AtomicAndTimer*>(pWorkStructure);
  31. // A series of atomic operations copied from the atomic unit test
  32. at.mLocalTimer.Start();
  33. ++(at.mAtomicInteger);
  34. --(at.mAtomicInteger);
  35. (at.mAtomicInteger) += 5;
  36. (at.mAtomicInteger) -= 5;
  37. (at.mAtomicInteger)++;
  38. (at.mAtomicInteger)--;
  39. at.mLocalTimer.Stop();
  40. return 0;
  41. }
  42. // --------------------------------------------------------------------------
  43. //
  44. // todo: come up with a performance test for CAS operations.
  45. // static intptr_t AtomicIntCompareAndSwap(void* pArgs)
  46. // {
  47. // AtomicAndTimer& at = static_cast<AtomicAndTimer&>(*pArgs);
  48. //
  49. // toCAS->mLocalTimer.Start();
  50. // toCAS->mAtomicInteger.SetValueConditional(0, 1);
  51. // toCAS->mLocalTimer.Stop();
  52. //
  53. // return 0;
  54. // }
  55. // ---------------------------------------------------------------------------
  56. //
  57. void AtomicIntPerfTest(ThreadEntryFunction ptestFunc, benchmarkenvironment::Sample &sample)
  58. {
  59. static const int kNumThreads = 8;
  60. EA::Thread::Thread::Status threadExitStatus;
  61. AtomicAndTimer threadTimers[kNumThreads];
  62. float totalTime = 0.0;
  63. Thread threads[kNumThreads];
  64. for (int i = 0; i < kNumThreads; ++i)
  65. threads[i].Begin(ptestFunc, &threadTimers[i]);
  66. for (int i = 0; i < kNumThreads; ++i)
  67. {
  68. threadExitStatus = threads[i].WaitForEnd(GetThreadTime() + 30000);
  69. // Only take the results if the thread exited properly.
  70. if (threadExitStatus != Thread::kStatusRunning)
  71. totalTime += threadTimers[i].mLocalTimer.AsSeconds();
  72. }
  73. sample.AddElement(totalTime);
  74. }
  75. // ------------------------------------------------------------------------------
  76. // NOTE If you wish to add tests here. You will need to add your test function to the
  77. // testFunctions vector, as well as the name of the test to the testNames vector.
  78. void PerfTestThreadAtomic(benchmarkenvironment::Results &results, EA::IO::FileStream* pPerformanceLog)
  79. {
  80. using namespace eastl;
  81. using namespace benchmarkenvironment;
  82. const int kNumSamples = 50;
  83. vector<ThreadEntryFunction> testFunctions;
  84. testFunctions.push_back(&AtomicIntMath);
  85. // The compare-and-swap test has been deactivated until we can think of a better way to test that functionality.
  86. //testFunctions.push_back(&AtomicIntCompareAndSwap));
  87. vector<string> testNames;
  88. testNames.push_back("Atomic Math Test");
  89. //testNames.push_back("Atomic Compare and Swap Test");
  90. vector<Sample> samples;
  91. for (unsigned int i = 0; i < testFunctions.size(); ++i)
  92. samples.push_back(Sample(kNumSamples));
  93. for (unsigned int i = 0; i < testFunctions.size(); ++i)
  94. {
  95. for (int j = 0; j < kNumSamples; ++j)
  96. AtomicIntPerfTest(testFunctions[i], samples[i]);
  97. AddRowToResults(results, samples[i], testNames.at(i));
  98. WriteToLogFile(pPerformanceLog, "%s,%g,%g\r\n", testNames[i].c_str(), samples[i].GetMean(), samples[i].GetVariance());
  99. }
  100. }
  101. #endif // EA_THREADS_AVAILABLE