关键词搜索

源码搜索 ×
×

tars源码分析之3

发布2022-07-03浏览386次

详情内容

buffer pool的实现,也非常经典:

  1. #include "util/tc_buffer_pool.h"
  2. #include <cassert>
  3. #include <sstream>
  4. #include <iomanip>
  5. inline static std::size_t RoundUp2Power(std::size_t size)
  6. {
  7. if (size == 0)
  8. return 0;
  9. size_t roundUp = 1;
  10. while (roundUp < size)
  11. roundUp *= 2;
  12. return roundUp;
  13. }
  14. namespace tars
  15. {
  16. TC_Slice::TC_Slice(void* d, size_t dl, size_t l) :
  17. data(d),
  18. dataLen(dl),
  19. len(l)
  20. {
  21. }
  22. TC_BufferPool::TC_BufferPool(size_t minBlock, size_t maxBlock) :
  23. _minBlock(RoundUp2Power(minBlock)),
  24. _maxBlock(RoundUp2Power(maxBlock)),
  25. _maxBytes(1024 * 1024), // pool所分配的内存不能超过它,否则直接new和delete,避免占用过高内存
  26. _totalBytes(0) // pool中的内存
  27. {
  28. /*
  29. * minBlock表示该pool所负责的最小内存分配,向上取整,比如20字节,取整为32
  30. * maxBlock表示该pool所负责的最大内存分配,向上取整,比如1000字节,取整为1024
  31. * listCount是计算buffer链表的数量,比如minBlock是32,maxBlock是64,那么只需要两个链表
  32. */
  33. size_t listCount = 0;
  34. size_t testVal = _minBlock;
  35. while (testVal <= _maxBlock)
  36. {
  37. testVal *= 2;
  38. ++ listCount;
  39. }
  40. assert (listCount > 0);
  41. _buffers.resize(listCount);
  42. }
  43. TC_BufferPool::~TC_BufferPool()
  44. {
  45. std::vector<BufferList>::iterator it(_buffers.begin());
  46. for (; it != _buffers.end(); ++ it)
  47. {
  48. BufferList& blist = *it;
  49. BufferList::iterator bit(blist.begin());
  50. for ( ; bit != blist.end(); ++ bit)
  51. {
  52. //delete[] (*bit);
  53. delete[] reinterpret_cast<char*>(*bit);
  54. }
  55. }
  56. }
  57. TC_Slice TC_BufferPool::Allocate(size_t size)
  58. {
  59. TC_Slice s;
  60. size = RoundUp2Power(size);
  61. if (size == 0)
  62. return s;
  63. if (size < _minBlock || size > _maxBlock)
  64. {
  65. // 不归pool管理,直接new
  66. s.data = new char[size];
  67. s.len = size;
  68. }
  69. else
  70. {
  71. // 定位到具体的buffer链表
  72. BufferList& blist = _GetBufferList(size);
  73. s = _Allocate(size, blist);
  74. }
  75. return s;
  76. }
  77. void TC_BufferPool::Deallocate(TC_Slice s)
  78. {
  79. if (s.len < _minBlock || s.len > _maxBlock)
  80. {
  81. // 不归pool管理,直接delete
  82. delete[] reinterpret_cast<char*>(s.data);
  83. }
  84. else if (_totalBytes >= _maxBytes)
  85. {
  86. // 占用内存过多,就不还给pool
  87. delete[] reinterpret_cast<char*>(s.data);
  88. }
  89. else
  90. {
  91. // 还给pool
  92. BufferList& blist = _GetBufferList(s.len);
  93. blist.push_back(s.data);
  94. _totalBytes += s.len;
  95. }
  96. }
  97. void TC_BufferPool::SetMaxBytes(size_t bytes)
  98. {
  99. _maxBytes = bytes;
  100. }
  101. size_t TC_BufferPool::GetMaxBytes() const
  102. {
  103. return _maxBytes;
  104. }
  105. std::string TC_BufferPool::DebugPrint() const
  106. {
  107. std::ostringstream oss;
  108. oss << "\n===============================================================\n";
  109. oss << "============ BucketCount " << std::setiosflags(std::ios::left) << std::setw(4) << _buffers.size() << " ================================" << std::endl;
  110. oss << "============ PoolBytes " << std::setw(10) << _totalBytes << " ============================" << std::endl;
  111. int bucket = 0;
  112. size_t size = _minBlock;
  113. std::vector<BufferList>::const_iterator it(_buffers.begin());
  114. for (; it != _buffers.end(); ++ it)
  115. {
  116. const BufferList& blist = *it;
  117. oss << "== Bucket " << std::setw(3) << bucket
  118. << ": BlockSize " << std::setw(8) << size
  119. << " Remain blocks " << std::setw(6) << blist.size()
  120. << " ======== \n";
  121. ++ bucket;
  122. size *= 2;
  123. }
  124. return oss.str();
  125. }
  126. TC_Slice TC_BufferPool::_Allocate(size_t size, BufferList& blist)
  127. {
  128. assert ((size & (size - 1)) == 0);
  129. TC_Slice s;
  130. s.len = size;
  131. if (blist.empty())
  132. {
  133. s.data = new char[size];
  134. }
  135. else
  136. {
  137. // 直接从链表中取出buffer
  138. s.data = *blist.begin();
  139. blist.pop_front();
  140. _totalBytes -= s.len;
  141. }
  142. return s;
  143. }
  144. TC_BufferPool::BufferList& TC_BufferPool::_GetBufferList(size_t s)
  145. {
  146. const BufferList& blist = const_cast<const TC_BufferPool& >(*this)._GetBufferList(s);
  147. return const_cast<BufferList& >(blist);
  148. }
  149. const TC_BufferPool::BufferList& TC_BufferPool::_GetBufferList(size_t s) const
  150. {
  151. assert ((s & (s - 1)) == 0);
  152. assert (s >= _minBlock && s <= _maxBlock);
  153. size_t index = _buffers.size();
  154. size_t testVal = s;
  155. while (testVal <= _maxBlock)
  156. {
  157. testVal *= 2;
  158. index --;
  159. }
  160. return _buffers[index];
  161. }
  162. } // end namespace tars

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载