高性能流媒体服务器-nebula之数据结构(4)--动态数组NBAArray
2016-09-01 13:09
447 查看
NBAArray是一个不使用realloc分配内存的动态数组,当数组动态增长时,我们使用bucket指数级的分配内存,将动态数组的内存分配分散到各个bucket,避免了数组内存分配时的数据复制,使用场景:数据push很频繁的时候。经与stl中的vector比较测试,push时nbaarray比vector高出近5倍的性能,get时比vector慢3倍左右。在服务器系统中,有着非常均衡的稳定性。
// // NBAArray.h // nebula // // Created by yi.cheng on 16/5/10. // Copyright © 2016年 kanshansoft. All rights reserved. // #ifndef NBAArray_h #define NBAArray_h #include #include #include /******************************************************************************/ /* array */ /** * Initial and minimal size of the array expressed as a power of 2. * The initial size is 2^NBA_ARRAYOF_BIT. */ #define NBA_ARRAYOF_BIT 6 /** \internal * Max number of elements as a power of 2. */ #define NBA_ARRAYOF_BIT_MAX 32 /** * Array container type. * \note Don't use internal fields directly, but access the container only using functions. */ template class NBAArray { NBAArray(const NBAArray&); NBAArray& operator = (const NBAArray&); public: NBAArray(lfalloctor& alloctor); const T& operator [](uint32_t index) const; T& editItemAt(uint32_t index); void push(const T& item); void push(T&& item); const T& begin() const; const T& last() const; INLINE uint32_t size() const { return mCount; } INLINE bool isEmpty() const { return (mCount == 0); } void clear(); ~NBAArray(); private: void* mBucket[NBA_ARRAYOF_BIT_MAX]; /**< Dynamic array of buckets. */ size_t mElementSize; /**< Size of the stored element in bytes. */ uint32_t mBucketBit; /**< Bits used in the bit mask. */ uint32_t mBucketMax; /**< Number of buckets. */ uint32_t mCount; /**< Number of initialized elements in the array. */ uint32_t mDefaultBucketNum; lfalloctor& mAlloctor; void _grow(uint32_t count); void* getItem(uint32_t pos); const void* getItem() const; void* _itemRef(uint32_t pos); const void* _itemRef(uint32_t pos) const; }; template NBAArray::NBAArray(lfalloctor& alloctor) : mAlloctor(alloctor), mElementSize(sizeof(T)), mBucketBit(NBA_ARRAYOF_BIT), mBucketMax(1 << NBA_ARRAYOF_BIT) { mBucket[0] = mAlloctor.malloc(mBucketMax*mElementSize); mCount = 0; mDefaultBucketNum = mBucketMax; for (uint32_t i = 1; i < mBucketBit; ++i) { mBucket[i] = mBucket[0]; } } template INLINE void NBAArray::_grow(uint32_t count) { mCount = count; while (count > mBucketMax) { uint8_t* segment = (uint8_t*)mAlloctor.malloc(mBucketMax * mElementSize); /* store it adjusting the offset */ /* cast to ptrdiff_t to ensure to get a negative value */ mBucket[mBucketBit] = segment - (ptrdiff_t)mBucketMax * mElementSize; ++mBucketBit; mBucketMax = 1 << mBucketBit; } } template INLINE void* NBAArray::_itemRef(uint32_t pos) { unsigned char* ptr; uint32_t bsr; /* get the highest bit set, in case of all 0, return 0 */ bsr = ilog2_u32(pos | 1); ptr = (unsigned char*)mBucket[bsr]; return ptr + pos * mElementSize; } template INLINE const void* NBAArray::_itemRef(uint32_t pos) const { unsigned char* ptr; uint32_t bsr; /* get the highest bit set, in case of all 0, return 0 */ bsr = ilog2_u32(pos | 1); ptr = (unsigned char*)mBucket[bsr]; return ptr + pos * mElementSize; } template INLINE void NBAArray::push(const T& item) { uint32_t pos = mCount; _grow(pos + 1); void* ptr = _itemRef(pos); copy_type(static_cast(ptr), &item, 1); } template INLINE void NBAArray::push(T&& item) { uint32_t pos = mCount; _grow(pos + 1); void* ptr = _itemRef(pos); copy_type(static_cast(ptr), std::forward(item)); } template INLINE const T& NBAArray::begin() const { const T* e = static_cast(_itemRef(0)); return *e; } template INLINE const T& NBAArray::last() const { const T* e = static_cast(_itemRef(mCount-1)); return *e; } template INLINE const T& NBAArray::operator[](uint32_t index) const { const T* e = static_cast(_itemRef(index)); return *e; } template INLINE T& NBAArray::editItemAt(uint32_t index) { T* e = static_cast(_itemRef(index)); return *e; } template NBAArray::~NBAArray() { uint32_t i =0; uint32_t destructItems; if(!traits::has_trivial_dtor && mCount > 0) { destructItems = (mCount >= mDefaultBucketNum) ? mDefaultBucketNum : mCount; destroy_type(static_cast(mBucket[0]), destructItems); mCount -= destructItems; } mAlloctor.free(mBucket[0]); for (i = NBA_ARRAYOF_BIT; i < mBucketBit; ++i) { unsigned char* segment = (unsigned char*)mBucket[i]; ptrdiff_t fft = (((ptrdiff_t)1) << i); if(!traits::has_trivial_dtor && mCount > 0) { void* storePtr = segment + fft * mElementSize; destructItems = (mCount >= fft) ? (uint32_t)fft : mCount; destroy_type(static_cast(storePtr), destructItems); mCount -= destructItems; } mAlloctor.free(segment + fft * mElementSize); } } template void NBAArray::clear() { uint32_t i =0; uint32_t destructItems; if(!traits::has_trivial_dtor && mCount > 0) { destructItems = (mCount >= mDefaultBucketNum) ? mDefaultBucketNum : mCount; destroy_type(static_cast(mBucket[0]), destructItems); mCount -= destructItems; } for (i = NBA_ARRAYOF_BIT; i < mBucketBit; ++i) { unsigned char* segment = (unsigned char*)mBucket[i]; ptrdiff_t fft = (((ptrdiff_t)1) << i); if(!traits::has_trivial_dtor && mCount > 0) { void* storePtr = segment + fft * mElementSize; destructItems = (mCount >= fft) ? (uint32_t)fft : mCount; destroy_type(static_cast(storePtr), destructItems); mCount -= destructItems; } } } #endif /* NBAArray_h */
相关文章推荐
- 高性能流媒体服务器-nebula之数据结构(5)--动态数组DynArray
- 高性能流媒体服务器-nebula之数据结构(9)--双锁并发队列
- 高性能流媒体服务器-nebula之数据结构(1)--hash table介绍
- 高性能流媒体服务器-nebula之数据结构(6)--无节点内存分配的单、双链表
- 高性能流媒体服务器-nebula之数据结构(3)--AVL树定时器
- 高性能流媒体服务器-nebula之数据结构(7)--环形无锁队列
- 高性能流媒体服务器-nebula之数据结构(2)--pairing heap
- 高性能流媒体服务器-nebula之数据结构(8)--双链表实现的内存中立队列
- hive发杂数据结构的使用,struct,array,map
- 数据结构——DoubleArray Trie
- 已备份数据库的磁盘结构版本为611,服务器支持版本为539,无法还原或升级数据库
- 通过RTMP协议将AAC数据发送到流媒体服务器
- hive发杂数据结构的使用,struct,array,map
- 使用Nginx架设高性能流媒体服务器
- EasyDarwin开源流媒体服务器高性能设计之无锁队列
- 图解数据结构(1)——大圈表示法、动态数组和单向链表
- Twemproxy源码分析(四)数据结构(array和string)
- Julia:关于push 与 Array 和Dict 数据结构
- 常用数据结构及复杂度 array、LinkedList、List、Stack、Queue、Dictionary、SortedDictionary、HashSet、SortedSet
- 快速建立基于HTTP协议的高性能数据查询服务器