BuddyAllocatorBuilder.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <Tests/Framework/Framework.h>
  6. #include <AnKi/Util/BuddyAllocatorBuilder.h>
  7. #include <tuple>
  8. using namespace anki;
  9. /// Check if all memory has the same value.
  10. static int memvcmp(const void* memory, U8 val, PtrSize size)
  11. {
  12. const U8* mm = static_cast<const U8*>(memory);
  13. return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0;
  14. }
  15. ANKI_TEST(Util, BuddyAllocatorBuilder)
  16. {
  17. // Simple
  18. {
  19. BuddyAllocatorBuilder<32, Mutex> buddy(32);
  20. Array<U32, 2> addr;
  21. const Array<U32, 2> sizes = {58, 198010775};
  22. const Array<U32, 2> alignments = {21, 17};
  23. Bool success = buddy.allocate(sizes[0], alignments[0], addr[0]);
  24. ANKI_TEST_EXPECT_EQ(success, true);
  25. success = buddy.allocate(sizes[1], alignments[1], addr[1]);
  26. ANKI_TEST_EXPECT_EQ(success, true);
  27. // buddy.debugPrint();
  28. buddy.free(addr[0], sizes[0], alignments[0]);
  29. buddy.free(addr[1], sizes[1], alignments[1]);
  30. // printf("\n");
  31. // buddy.debugPrint();
  32. }
  33. // Fuzzy with alignment
  34. {
  35. BuddyAllocatorBuilder<32, Mutex> buddy(32);
  36. std::vector<std::tuple<U32, U32, U32, U8>> allocations;
  37. U8* backingMemory = static_cast<U8*>(malloc(kMaxU32));
  38. for(PtrSize i = 0; i < kMaxU32; ++i)
  39. {
  40. backingMemory[i] = i % kMaxU8;
  41. }
  42. for(U32 it = 0; it < 10000; ++it)
  43. {
  44. if((getRandom() % 2) == 0)
  45. {
  46. // Do an allocation
  47. U32 addr;
  48. const U32 size = U32(max<U64>(getRandom() % 256_MB, 1));
  49. const U32 alignment = max<U32>(getRandom() % 24, 1);
  50. const Bool success = buddy.allocate(size, alignment, addr);
  51. // printf("al %u %u\n", size, alignment);
  52. if(success)
  53. {
  54. const U8 bufferValue = getRandom() % kMaxU8;
  55. memset(backingMemory + addr, bufferValue, size);
  56. allocations.push_back({addr, size, alignment, bufferValue});
  57. }
  58. }
  59. else
  60. {
  61. // Do some deallocation
  62. if(allocations.size())
  63. {
  64. const PtrSize randPos = getRandom() % allocations.size();
  65. const U32 address = std::get<0>(allocations[randPos]);
  66. const U32 size = std::get<1>(allocations[randPos]);
  67. const U32 alignment = std::get<2>(allocations[randPos]);
  68. const U8 bufferValue = std::get<3>(allocations[randPos]);
  69. ANKI_TEST_EXPECT_EQ(memvcmp(backingMemory + address, bufferValue, size), 1);
  70. // printf("fr %u %u\n", size, alignment);
  71. buddy.free(address, size, alignment);
  72. allocations.erase(allocations.begin() + randPos);
  73. }
  74. }
  75. }
  76. free(backingMemory);
  77. // Get the fragmentation
  78. BuddyAllocatorBuilderStats stats;
  79. buddy.getStats(stats);
  80. ANKI_TEST_LOGI("Memory info: userAllocatedSize %zu, realAllocatedSize %zu, externalFragmentation %f, "
  81. "internalFragmentation %f",
  82. stats.m_userAllocatedSize, stats.m_realAllocatedSize, stats.m_externalFragmentation, stats.m_internalFragmentation);
  83. // Remove the remaining
  84. for(const auto& pair : allocations)
  85. {
  86. buddy.free(std::get<0>(pair), std::get<1>(pair), std::get<2>(pair));
  87. }
  88. }
  89. }