美文网首页
12 UE5 内存分配器Allocator介绍

12 UE5 内存分配器Allocator介绍

作者: 游戏开发程序员 | 来源:发表于2024-02-23 21:55 被阅读0次

内存分配器Allocator

  • 容器都依赖一个分配器,扩容和回收内存都通过分配器实现
  • 分配器是负责封装内存管理的对象]
  • 标准库STL容器使用它们来管理容器内部的所有内存分配
  • 动机是使容器完全独立于底层内存模型
  • 让程序员控制容器内的内存分配,而不是用底层硬件的地址模型

TAllocatorTraitsBase

  • 定义了一些特性
template <typename AllocatorType>
struct TAllocatorTraitsBase
{
    enum { IsZeroConstruct           = false };
    enum { SupportsFreezeMemoryImage = false };
    enum { SupportsElementAlignment  = false };
};

ContainerAllocationPolicies.h 接口类定义

  • 接口类 说明内存分配器是需要实现那些接口
  • 基础类型,他们的大小和内存占用是一致的,而结构体sizeof可能会大于成员大小总和.
  • 使用了内存对齐:让数据读取更高效,有些平台不对齐会崩溃
class FContainerAllocatorInterface
{
public:
    using SizeType = int32;

    enum { NeedsElementType = true };

    enum { RequireRangeCheck = true };

    //  A class that receives both the explicit allocation and implicit 
    template<typename ElementType>
    class ForElementType
    {
        void MoveToEmpty(ForElementType& Other);

        // 需要明确类型 ElementType
        template <typename OtherAllocatorType>
        void MoveToEmptyFromOtherAllocator(typename OtherAllocatorType::template ForElementType<ElementType>& Other);

        ElementType* GetAllocation() const;

        // NumBytesPerElement - The number of bytes/element.
        void ResizeAllocation(
            SizeType PreviousNumElements, SizeType NumElements, SIZE_T NumBytesPerElement);
  
               // exists SupportsElementAlignment == true 类似的重载函数就不列出
        void ResizeAllocation(SizeType PreviousNumElements,SizeType NumElements,SIZE_T NumBytesPerElement,
uint32 AlignmentOfElement);

        SizeType CalculateSlackReserve(
            SizeType NumElements,SIZE_T NumBytesPerElement) const;

        SizeType CalculateSlackShrink(
            SizeType NumElements,   SizeType CurrentNumSlackElements,SIZE_T NumBytesPerElement) const;

        SizeType CalculateSlackGrow(
            SizeType NumElements,   SizeType CurrentNumSlackElements,SIZE_T NumBytesPerElement) const;

        SIZE_T GetAllocatedSize(SizeType NumAllocatedElements, SIZE_T NumBytesPerElement) const;

        bool HasAllocation() const;

        SizeType GetInitialCapacity() const;
    };

    // NeedsElementType=false 时使用
    typedef ForElementType<FScriptContainerElement> ForAnyElementType;
};

实现的内存分配器

// 对一些默认分配器的定义
template <int IndexSize> class TSizedDefaultAllocator : public TSizedHeapAllocator<IndexSize> 
{ public: typedef TSizedHeapAllocator<IndexSize> Typedef; };

template<int IndexSize> class TSizedDefaultAllocator;
using FDefaultAllocator = TSizedDefaultAllocator<32>;

using FHeapAllocator = TSizedHeapAllocator<32>;

template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator>
using TInlineAllocator = TSizedInlineAllocator<NumInlineElements, 32, SecondaryAllocator>;
template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator64>
using TInlineAllocator64 = TSizedInlineAllocator<NumInlineElements, 64, SecondaryAllocator>;

UE的容器用的分配器定义

  • TSizedDefaultAllocator 继承 TSizedHeapAllocator
  • using FDefaultAllocator = TSizedDefaultAllocator<32>;
  • FString = FDefaultAllocator
  • TArray TSortedMap = FDefaultAllocator
  • TSet TMap TMultiMap = FDefaultSetAllocator
/// @cond DOXYGEN_WARNINGS
template<int IndexSize> class TSizedDefaultAllocator;
using FDefaultAllocator = TSizedDefaultAllocator<32>;
using FDefaultAllocator64 = TSizedDefaultAllocator<64>;
class FDefaultSetAllocator;

class FString;

template<> struct TIsContiguousContainer<FString> { static constexpr bool Value = true; };

template<typename T, typename Allocator = FDefaultAllocator> class TArray;
template<typename T> using TArray64 = TArray<T, FDefaultAllocator64>;
template<typename T, typename SizeType = int32> class TArrayView;
template<typename T> using TArrayView64 = TArrayView<T, int64>;
template<typename T, typename SizeType = int32> using TConstArrayView = TArrayView<const T, SizeType>;
template<typename T> using TConstArrayView64 = TConstArrayView<T, int64>;
template<typename T> class TTransArray;
template<typename InKeyType, typename InValueType, bool bInAllowDuplicateKeys> struct TDefaultMapHashableKeyFuncs;
template<typename InKeyType, typename InValueType, typename SetAllocator = FDefaultSetAllocator, typename KeyFuncs = TDefaultMapHashableKeyFuncs<InKeyType, InValueType, false> > class TMap;
template<typename KeyType, typename ValueType, typename SetAllocator = FDefaultSetAllocator, typename KeyFuncs = TDefaultMapHashableKeyFuncs<KeyType, ValueType, true > > class TMultiMap;
template <typename T = void > struct TLess;
template <typename> struct TTypeTraits;
template<typename InKeyType, typename InValueType, typename ArrayAllocator = FDefaultAllocator, typename SortPredicate = TLess<typename TTypeTraits<InKeyType>::ConstPointerType> > class TSortedMap;
template<typename ElementType,bool bInAllowDuplicateKeys = false> struct DefaultKeyFuncs;
template<typename InElementType, typename KeyFuncs = DefaultKeyFuncs<InElementType>, typename Allocator = FDefaultSetAllocator> class TSet;
template<typename InElementType, typename InSizeType = int32> class TStridedView;
template<typename T, typename SizeType = int32> using TConstStridedView = TStridedView<const T, SizeType>;
/// @endcond

FString的分配器TSizedDefaultAllocator == TSizedHeapAllocator

  • 使用的为类型为32的堆分配器 由FMemory管理控制内存
class FString
{
public:
    using AllocatorType = TSizedDefaultAllocator<32>;

template <int IndexSize> class TSizedDefaultAllocator : public TSizedHeapAllocator<IndexSize>
 { public: typedef TSizedHeapAllocator<IndexSize> Typedef; };

相关文章

网友评论

      本文标题:12 UE5 内存分配器Allocator介绍

      本文链接:https://www.haomeiwen.com/subject/lqnwadtx.html