ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析
文章目錄
- 內(nèi)存查看
- 內(nèi)存控制
- 內(nèi)存控制源碼分析
- 通過gperftools接口獲取osd進程實際內(nèi)存 動態(tài)設置cache大小
- 動態(tài)調(diào)整cache比例
- trim釋放內(nèi)存
本文通過對ceph-osd內(nèi)存查看跟蹤的5種手段以及osd內(nèi)存控制的方式進行源碼層面的說明,并未通過修改相關源碼進行控制(水平不夠),僅限于使用社區(qū)已開發(fā)好的參數(shù)進行相關配置的跟進而已,如想要追求更加精確的理解,可以對
osd/bluestore/rocksdb相關源碼實現(xiàn)進行閱讀
ceph版本
12.2.1 -
12.2.12
內(nèi)存查看
-
最常用的內(nèi)存初始查看方法
top -u ceph |grep ceph-osd,通過交互式輸入c,2次e即可看到如下效果。其中單個osd進程占用內(nèi)存為res欄
-
ceph tell osd.0 heap stats
這種方式主要查看osd運行過程中占用的內(nèi)存:
第一項:Bytes in use by application包括bluestore cache,rocksdb_cache,bluefs,pglog等數(shù)據(jù)信息
第二項:Bytes in page heap freelist內(nèi)存頁堆管理的空閑空間鏈表
第三項:Bytes in central cache freelist中心緩沖區(qū)占用
第四項:Bytes in transfer cache freelist交換緩沖區(qū)占用
第五項:Bytes in thread cache freelists線程緩沖區(qū)占用
第六項:Bytes in malloc metadatamalloc為元數(shù)據(jù)分配的空間ceph是使用tcmalloc 空間分配器進行空間分配,其中由tcmalloc分配的但是并未被ceph進程使用的空間可以通過
ceph tell osd.id heap release
-
google-perftools工具實時跟蹤osd/mon進程內(nèi)存占用,精確到具體的函數(shù)。關于pprof的安裝以及如何使用其來查看osd內(nèi)存占用,可以參考pprof搭配ceph tell命令分析ceph內(nèi)存
效果如下:(pprof) top10 Total: 2525 samples 298 11.8% 11.8% 345 13.7% runtime.mapaccess1_fast64 268 10.6% 22.4% 2124 84.1% main.FindLoops 251 9.9% 32.4% 451 17.9% scanblock 178 7.0% 39.4% 351 13.9% hash_insert 131 5.2% 44.6% 158 6.3% sweepspan 119 4.7% 49.3% 350 13.9% main.DFS96 3.8% 53.1% 98 3.9% flushptrbuf95 3.8% 56.9% 95 3.8% runtime.aeshash6495 3.8% 60.6% 101 4.0% runtime.settype_flush88 3.5% 64.1% 988 39.1% runtime.mallocgc...各個參數(shù)含義如下:
-
The first column contains the direct memory use in MB. 函數(shù)本身使用的內(nèi)存
-
The fourth column contains memory use by the procedure and all of its callees.函數(shù)本身內(nèi)存+調(diào)用函數(shù)內(nèi)存
-
The second and fifth columns are just percentage representations of the numbers in the first and fourth columns. 第二第五列分別為第一列,第四列與total的比值
-
The third column is a cumulative sum of the second column.第三列為(到當前行數(shù)為止)第二列所有的和
注意:該命令需要
heap start_profiler長期運行才能夠利用pprof抓取更多有效信息。 -
-
ceph原生命令,由ceph內(nèi)存池(bstore線程)管理的內(nèi)存各項數(shù)據(jù)占用,可以通過調(diào)整
mempool_debug = true參數(shù)來查看詳細打印
ceph daemon osd.16 dump_mempools
打印信息如下:
這里能夠看到內(nèi)存池中各個數(shù)據(jù)結(jié)構(gòu)的items個數(shù)和bytes總空間大小,關于當前命令如何動態(tài)獲取各個數(shù)據(jù)結(jié)構(gòu)的內(nèi)容相關得源碼分析可以參考admin_socket實時獲取內(nèi)存池數(shù)據(jù) 文章
-
valgrind搭配massif,查看進程內(nèi)存占用,能夠看到內(nèi)存分配棧并且精確到具體的函數(shù);詳細的配置以及更加高級全面的內(nèi)存查看方法可以參考valgrind搭配massif、vgdb分析ceph-mon內(nèi)存
linux端的mon進程占用效果查看如下:
最下側(cè)即為進程內(nèi)存占用棧,并且在運行時間點上提供快照以及峰值的內(nèi)存占用情況,能夠很清晰得看到各個時間點內(nèi)存如何上漲上來,同時massif提供可視化的圖形頁面(火焰圖)來查看進程內(nèi)存:
內(nèi)存控制
本文的內(nèi)存控制版本基于ceph 12.2.12版本,相關的參數(shù)描述同樣是基于12.2.12版本,當前12.2.12ceph版本真正實現(xiàn)了osd進程內(nèi)存的精準控制
bluestore相關參數(shù)說明
bluestore_min_alloc_size_hdd = 65536 #hdd做osd時的bluestore 分配空間的最小粒度 64K
bluestore_min_alloc_size_ssd = 16384 #ssd做osd時bluestore分配空間的最小粒度 16K
bluestore_cache_size_hdd = 1073741824 #hdd做osd時的bluestore_cache的大小,1G,該參數(shù)主要用于緩存元數(shù)據(jù),鍵值數(shù)據(jù)以及部分data數(shù)據(jù)
bluestore_cache_size_ssd = 3221225472 #ssd做osd時的bluestore_cache的大小,默認3G
bluestore_cache_trim_interval = 0.05 #bluestore cache 裁剪的時間間隔,每隔0.05秒會嘗試對不使用的cache種的數(shù)據(jù)(onode,blob,extents)釋放
bluestore_cache_trim_max_skip_pinned = 64 #每次trim時的onode的個數(shù)
osd內(nèi)存相關控制參數(shù)
osd_memory_base = 805306368 #osd內(nèi)存占用的最小值,默認768M
osd_memory_target = 838860800 # 真正限制osd內(nèi)存的上限,即我們top 種看到的進程實際內(nèi)存占用會維持在當前參數(shù)設置的值以下。這里我們設置的800M
osd_memory_cache_min = 134217728 #osd 內(nèi)存 cache占用的最小值,128M
osd_memory_cache_resize_interval = 1.0 #osd cache大小的實際調(diào)整的時間間隔,每隔1秒,進行一次cache大小的調(diào)整
bluestore_cache_autotune_interval = 5 #osd每隔5秒調(diào)整一次bluestore cache的比例
bluestore_cache_autotune_chunk_size = 33554432 #osd每次調(diào)整 bluestore cache的最小單位,32M
bluestore_cache_kv_ratio = 0.4 #bluestore cache 存儲鍵值cache的比例
bluestore_cache_meta_ratio = 0.4 #bluestore cache 存儲元數(shù)據(jù)cache的比例
內(nèi)存控制源碼分析
主要內(nèi)存控制方式是通過在osd_memory_cache_resize_interval時間間隔內(nèi)獲取osd進程的實際內(nèi)存,判斷其是否超過設定的osd_memory_target的數(shù)值,并進行cache大小的調(diào)整,最終通過trim釋放內(nèi)存。
關鍵地實現(xiàn)難點為以下幾個地方:
- 獲取osd進程的實際內(nèi)存
- 動態(tài)調(diào)整cache比例
- 動態(tài)設置cache大小
- trim釋放內(nèi)存
通過gperftools接口獲取osd進程實際內(nèi)存 動態(tài)設置cache大小
因為ceph內(nèi)存分配使用的tcmalloc進行的,ceph這里是通過gperftools提供的獲取tcmalloc內(nèi)存分配的接口進行獲取
src/os/bluestore/BlueStore.cc 在bstore的線程函數(shù)種void *BlueStore::MempoolThread::entry()
通過_tune_cache_size調(diào)用gperttools提供的tcmalloc獲取內(nèi)存分配的接口獲取內(nèi)存大小
將最終需要調(diào)整的cache大小已全局變量auto_tune_size返回
關于gperftools獲取已占有內(nèi)存的接口實現(xiàn)可以github下載gperftools-master源碼https://github.com/gperftools/gperftools,這里僅貼出將未使用內(nèi)存頁但以申請的內(nèi)存頁釋放回操作系統(tǒng)的代碼調(diào)用,其他獲取總的內(nèi)存頁接口和未使用內(nèi)存頁接口詳細實現(xiàn)有興趣的同學可以去看看:
void ceph_heap_release_free_memory()
{MallocExtension::instance()->ReleaseFreeMemory();
}void MallocExtension::ReleaseFreeMemory() {ReleaseToSystem(static_cast<size_t>(-1)); // SIZE_T_MAX
}virtual void ReleaseToSystem(size_t num_bytes) {SpinLockHolder h(Static::pageheap_lock());if (num_bytes <= extra_bytes_released_) {// We released too much on a prior call, so don't release any// more this time.extra_bytes_released_ = extra_bytes_released_ - num_bytes;return;}num_bytes = num_bytes - extra_bytes_released_;// num_bytes might be less than one page. If we pass zero to// ReleaseAtLeastNPages, it won't do anything, so we release a whole// page now and let extra_bytes_released_ smooth it out over time.Length num_pages = max<Length>(num_bytes >> kPageShift, 1);size_t bytes_released = Static::pageheap()->ReleaseAtLeastNPages(num_pages) << kPageShift;if (bytes_released > num_bytes) {extra_bytes_released_ = bytes_released - num_bytes;} else {// The PageHeap wasn't able to release num_bytes. Don't try to// compensate with a big release next time. Specifically,// ReleaseFreeMemory() calls ReleaseToSystem(LONG_MAX).extra_bytes_released_ = 0;}}
動態(tài)調(diào)整cache比例
關于bluestore cache的作用,很明顯,將高命中的臟數(shù)據(jù)(kv數(shù)據(jù),元數(shù)據(jù))等數(shù)據(jù)放入到緩存種,加速bluestore io讀寫能力。
其中bluestore cache維護了一個cache優(yōu)先級列表如下
最高優(yōu)先級為kv cache,其次 meta cache,最后剩余的提供給data cache。
優(yōu)先級越高的cache,分配內(nèi)存資源,調(diào)整內(nèi)存資源優(yōu)先分配。當然占用的大小則是由我們以上圖的兩個ratio參數(shù)進行控制。
- 初始化cache,設置優(yōu)先級cache內(nèi)存占用的比例
_adjust_cache_settings(); void BlueStore::MempoolThread::_adjust_cache_settings() {store->db->set_cache_ratio(store->cache_kv_ratio);meta_cache.set_cache_ratio(store->cache_meta_ratio);data_cache.set_cache_ratio(store->cache_data_ratio); } - 動態(tài)調(diào)整 cache
從動態(tài)設置cache大小中tune_cache_size獲取到的可以分配的cache大小auto_tune_cache_size,將其根據(jù)各個cache的ratio比例分配給優(yōu)先級cache
針對每個優(yōu)先級Cache的大小調(diào)整則遵循如下規(guī)則:void BlueStore::MempoolThread::_balance_cache( const std::list<PriorityCache::PriCache *>& caches) {//初始值為osd內(nèi)存最小值 osd_memory_cache_min 128M,該值在tune_cache_size種動態(tài)調(diào)整int64_t mem_avail = autotune_cache_size;//根據(jù)對應cache的優(yōu)先級進行cache容量的分配// Assign memory for each priority levelfor (int i = 0; i < PriorityCache::Priority::LAST + 1; i++) {ldout(store->cct, 10) << __func__ << " assigning cache bytes for PRI: " << i << dendl;PriorityCache::Priority pri = static_cast<PriorityCache::Priority>(i);_balance_cache_pri(&mem_avail, caches, pri);}//將剩余的未分配的cache 按照比例再重新分配// Assign any leftover memory based on the default ratios.if (mem_avail > 0) {for (auto it = caches.begin(); it != caches.end(); it++) {int64_t fair_share =static_cast<int64_t>((*it)->get_cache_ratio() * mem_avail);if (fair_share > 0) {(*it)->add_cache_bytes(PriorityCache::Priority::LAST, fair_share);}}}// assert if we assigned more memory than is available.assert(mem_avail >= 0);// Finally commit the new cache sizesfor (auto it = caches.begin(); it != caches.end(); it++) {(*it)->commit_cache_size();} }- 獲取優(yōu)先級cache想要的容量,通過
bluestore_cache_autotune_chunk_size34M單位進行分配 - 優(yōu)先級cache 想要的容量大于cache剩余容量,將cache剩余的容量都提供給當前優(yōu)先級cache
- 優(yōu)先級cache 想要的容量小于cache剩余容量,直到分配足夠
- 獲取優(yōu)先級cache想要的容量,通過
trim釋放內(nèi)存
每隔bluestore_cache_trim_interval會嘗試釋放一次內(nèi)存,每次嘗試釋放元數(shù)據(jù)的個數(shù)為bluestore_cache_trim_max_skip_pinned,釋放內(nèi)存后當osd總內(nèi)存超過osd_memory_target,則不再進行cache相關的大小調(diào)整;否則仍然繼續(xù)將未超過的部分應用于cache分配。
計算好需要trim的元數(shù)據(jù)個數(shù)和緩存大小,調(diào)用對應的cache trim函數(shù)。
bluestore默認使用的是淘汰算法更優(yōu)的TwoQCache,則調(diào)用對應的void BlueStore::TwoQCache::_trim(uint64_t onode_max, uint64_t buffer_max)執(zhí)行內(nèi)存釋放即可。
關于內(nèi)存控制,osd_memoiry_target及其一系列控制衍生參數(shù)尤為關鍵。ceph在L版本低版本并未做得足夠完善,但是L版本的最新版已經(jīng)將內(nèi)存控制邏輯完善,總之在保證性能的前提下OSD內(nèi)存控制更加更加精準。
總結(jié)
以上是生活随笔為你收集整理的ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞度最低配多少钱?
- 下一篇: ceph bluestore源码分析:a