BuddyAllocatorBuilder.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright (C) 2009-2022, 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. HeapAllocator<U8> alloc(allocAligned, nullptr);
  18. // Simple
  19. {
  20. BuddyAllocatorBuilder<32, Mutex> buddy(alloc, 32);
  21. Array<U32, 2> addr;
  22. const Array<U32, 2> sizes = {58, 198010775};
  23. const Array<U32, 2> alignments = {21, 17};
  24. Bool success = buddy.allocate(sizes[0], alignments[0], addr[0]);
  25. ANKI_TEST_EXPECT_EQ(success, true);
  26. success = buddy.allocate(sizes[1], alignments[1], addr[1]);
  27. ANKI_TEST_EXPECT_EQ(success, true);
  28. // buddy.debugPrint();
  29. buddy.free(addr[0], sizes[0], alignments[0]);
  30. buddy.free(addr[1], sizes[1], alignments[1]);
  31. // printf("\n");
  32. // buddy.debugPrint();
  33. }
  34. // Fuzzy with alignment
  35. {
  36. BuddyAllocatorBuilder<32, Mutex> buddy(alloc, 32);
  37. std::vector<std::tuple<U32, U32, U32, U8>> allocations;
  38. U8* backingMemory = static_cast<U8*>(malloc(MAX_U32));
  39. for(PtrSize i = 0; i < MAX_U32; ++i)
  40. {
  41. backingMemory[i] = i % MAX_U8;
  42. }
  43. for(U32 it = 0; it < 10000; ++it)
  44. {
  45. if((getRandom() % 2) == 0)
  46. {
  47. // Do an allocation
  48. U32 addr;
  49. const U32 size = max<U32>(getRandom() % 256_MB, 1);
  50. const U32 alignment = max<U32>(getRandom() % 24, 1);
  51. const Bool success = buddy.allocate(size, alignment, addr);
  52. // printf("al %u %u\n", size, alignment);
  53. if(success)
  54. {
  55. const U8 bufferValue = getRandom() % MAX_U8;
  56. memset(backingMemory + addr, bufferValue, size);
  57. allocations.push_back({addr, size, alignment, bufferValue});
  58. }
  59. }
  60. else
  61. {
  62. // Do some deallocation
  63. if(allocations.size())
  64. {
  65. const PtrSize randPos = getRandom() % allocations.size();
  66. const U32 address = std::get<0>(allocations[randPos]);
  67. const U32 size = std::get<1>(allocations[randPos]);
  68. const U32 alignment = std::get<2>(allocations[randPos]);
  69. const U8 bufferValue = std::get<3>(allocations[randPos]);
  70. ANKI_TEST_EXPECT_EQ(memvcmp(backingMemory + address, bufferValue, size), 1);
  71. // printf("fr %u %u\n", size, alignment);
  72. buddy.free(address, size, alignment);
  73. allocations.erase(allocations.begin() + randPos);
  74. }
  75. }
  76. }
  77. free(backingMemory);
  78. // Get the fragmentation
  79. BuddyAllocatorBuilderStats stats;
  80. buddy.getStats(stats);
  81. ANKI_TEST_LOGI("Memory info: userAllocatedSize %zu, realAllocatedSize %zu, externalFragmentation %f, "
  82. "internalFragmentation %f",
  83. stats.m_userAllocatedSize, stats.m_realAllocatedSize, stats.m_externalFragmentation,
  84. stats.m_internalFragmentation);
  85. // Remove the remaining
  86. for(const auto& pair : allocations)
  87. {
  88. buddy.free(std::get<0>(pair), std::get<1>(pair), std::get<2>(pair));
  89. }
  90. }
  91. }