13
OSv malloc(日本語版) Satoru Takeuchi <[email protected]>

OSv malloc

Embed Size (px)

Citation preview

Page 1: OSv malloc

OSv malloc(日本語版)Satoru Takeuchi<[email protected]>

Page 2: OSv malloc

はじめに● 本記事はOSv Advent Calendar[1] 21日目の記事● 前提知識

○ OS/OSvについて、参考文献[2]程度の基礎知識○ C++の言語仕様○ 基本的なアルゴリズム、データ構造の知識○ Linux kernelのソースを読んだことがあれば、なおよい

● 調査対象ソースは12/21日現在におけるupstreamのmaster branch[3]○ HEAD commit: f7d3ddd648b38789daa8287626a66863a780f139○ 簡単のため、デバッグ機能やトレース機能、排他制御については無視

● 以後、パス名はOSv ソースコードのトップディレクトリからの相対パス

Page 3: OSv malloc

概要● 定義はcore/mempool.cに存在: ファイルサイズは2K行弱

○ 実装はシンプル○ コメントにも”Our malloc() is very coarse”とか書いてたりする

● 小さなobjectの取得に特化(JVMのためか?)● カーネル空間でもユーザ空間でも全く同じmalloc()を使う

○ それがOSv way○ linux kernelでいうとアプリがkmalloc()を直接呼ぶイメージ

● 実際のobject獲得sizeは2^n >= 8バイト(nは正の整数)に切り上げられる○ 例) 4byte要求すると8byteのobjectを獲得

Page 4: OSv malloc

構成● memory objectのsizeに応じて異なる仕組みを利用

○ <= 1KiB: mempool○ > 1KiB: page allocator

user or kernelmempool

(Linux kernelのsl[auo]bに相当)

memory管理subsystem

page allocator(Linux kernelの

buddy allocatorに相当

malloc()/free()

Page 5: OSv malloc

簡単な実行の流れmalloc(size) - > std_malloc(size, align) (*1) sizeを2^n >= 8 (nは正の整数)バイトに切り上げ if (1KiB以下の獲得 && SMP用初期化後) # 後者はアプリなら常に真 malloc_pools[lg(n)].alloc() # mempoolより割り当て else if (1KiB<size<=4KiBの割り当て) memory::alloc_page() # page allocatorより1pageを割り当て else malloc_larger() # page allocatorより複数pageを割り当て # 3つの中で一番複雑な論理(説明は割愛)

*1) posix_memalign()などによって明にalignmentを指定した場合は、もう少し 込み入った条件分岐をする。詳細はstd_malloc()のコードを参照

Page 6: OSv malloc

1KiB以下の割り当て● 前述のようにmempoolを使用

○ class malloc_pool(class poolを継承)によって管理● 定義: “malloc_pool malloc_pools[]”

○ malloc()で獲得するobject sizeごとに存在するmempool○ 要素数はlg(page size)+1。x86_64ならpage sizeが4KiBなので12+1=13○ それぞれsizeが1,2,4,8,...,4KiB,8KiBのsizeの割り当てに対応

■ 最後の8KiBの要素の必要性がよくわからない...○ アプリが使う範囲ではmempool[11,…,(page_size+1)]は未使用

Page 7: OSv malloc

mempoolのしくみ● slab allocator[4]のOSv版。page size以下の小さなsizeの割り当てに使用

○ class poolによって管理 # えらく汎用的な名前…● 8byteから4KiBまでのsizeのobjectを扱う

○ size <=1KiB: 1page内に複数objectを配置○ 1KiB < size <= 4KiB: 1page内に1object

● MP環境におけるスケーラビリティ向上のためのper-CPU cacheを持つ○ 参照の局所性により、object獲得時に自CPUが最近使用した、つまり

cacheに残っているmemoryを使える可能性が向上○ CPUごとの領域だけ使っている限りは、排他制御不要

● これ以上の詳細は”Memory allocation strategy”で始まるcommentや、ソースコードを参照

Page 8: OSv malloc

page allocatorのしくみ● page sizeのmemory割り当て

○ class page_range_allocatorによって管理● L1, L2という2levelのcacheを持つ

○ L1: per-CPU cache○ L2: global cache

● cacheの下の最下層をglobal page allocatorと呼ぶ

kernel subsystem(mempool含む)

L1 cache(per-CPU cache)

L2 cache(全CPUで共有)

globalpage

allocator

page allocator

Page 9: OSv malloc

page allocator: L1 cache● per-CPUのcache● struct l1を用いて管理

○ cacheするpage数 <=l1::max(512)● 定義: “l1 percpu_l1[<CPU数>]”● UI: 名前が*_localなら、内部で同期獲得/開放しない

○ page獲得: l1::alloc_page{,_local}○ page開放: l1::free_page{,_local}

● L2 cacheとのインターフェイス○ 非同期: per-CPU thread(“page_pool_l1_<cpu>”)を用いる

■ 残数 < l1::max*¼ => 複数pageを獲得■ 残数 > l1::max*¾ => 複数pageを開放

○ 同期: 残数が0, l1::maxになれば、それぞれ同期的に複数pageを獲得/開放

Page 10: OSv malloc

page allocator: L2 cache● 全CPU共通のcache● class l2を用いて管理

○ cacheするpage数は最多でl2::max)● (L1 cacheが使う)UI: 名前が”try_*”なら、内部で同期獲得/開放しない

○ 複数page獲得: l2::{try_,}alloc_page_batch○ 複数page開放: l2::{try_,}free_page_batch

● global page allocatorとのインターフェイス● 非同期: per-CPU thread(“page_pool_l2”)を用いる

○ 残数 < l2::max*¼ => 複数pageを獲得○ 残数 > l2::max*¾ => 複数pageを開放

○ 同期: 残数が0, l2::maxになれば、それぞれ同期的に複数pageを獲得/開放

Page 11: OSv malloc

page allocator: global page allocator

● OSvのメモリ管理subsystem最深部に存在するコンポーネント● systemの生の空きpageを管理● 今回は時間の都合により、説明を割愛

Page 12: OSv malloc

参考文献

1. OSv Advent Calendar2014http://qiita.com/advent-calendar/2014/osv

2. OSvのご紹介 in OSC2014 Tokyo/Fall, Takuya ASADA, Cloudius Systemshttp://www.slideshare.net/syuu1228/osv-in-osc2014-tokyofall

3. OSvのsource codehttps://github.com/cloudius-systems/osv

4. slab allocation at Wikipediahttp://en.wikipedia.org/wiki/Slab_allocation

5. mallocの旅(Glibc編), こさき@ぬまづhttp://www.slideshare.net/kosaki55tea/glibc-malloc

Page 13: OSv malloc

おまけ: OSvのコードを読んでみた感想

● malloc()の実装を読むはずが、結局カーネルのメモリ管理のコードをかなり読むはめに陥った。が、勉強になったのでよしとする

● ソースがコンパクトで、今やすっかり巨大化したLinux kernelに比べると、はるかに読みやすい○ まだまだコード最適化による性能の伸びしろがある○ 息抜き/勉強用に気軽に読めるのでOSの学習にいいかも

● malloc(size)以外にmalloc(size, align)という、posix_memalign()に似た関数もある

アプリにはexportしていないため、kernelのみが使用可能

C++のoverload機能があったからできる。ビバC++