LoginSignup
5
3

More than 3 years have passed since last update.

Rustのslabってなんなのさ

Posted at

この記事を書いたきっかけ

Rustのコードを読んでいたら

let mut connections = Slab::new();

このような記述が出てきて,ここ以外でもこのSlabがでてきたので今日はこのSlabについて調べて,自分なりに理解できるようにまとめてみました。

まず,slabクレートについて

slabクレート

公式ドキュメントによると,

Pre-allocated storage for a uniform data type.

Slab provides pre-allocated storage for a single data type. If many values of a single type are being allocated, it can be more efficient to pre-allocate the necessary storage. Since the size of the type is uniform, memory fragmentation can be avoided. Storing, clearing, and lookup operations become very cheap.

While Slab may look like other Rust collections, it is not intended to be used as a general purpose collection. The primary difference between Slab and Vec is that Slab returns the key when storing the value.

It is important to note that keys may be reused. In other words, once a value associated with a given key is removed from a slab, that key may be returned from future calls to insert.

slabは,ひとつの型に統一されたデータのための,プリアロケートされたストレージのことを指しているみたいです。
型の統一されたデータを管理する際はこのslabを用いると,メモリフラグメンテーションを避けることができるので効率的にメモリ割り当てができるようです。

サンプルコード

公式ドキュメントに載っていたサンプルのコードです。

let mut slab = Slab::new();

let hello = slab.insert("hello");
let world = slab.insert("world");

assert_eq!(slab[hello], "hello");
assert_eq!(slab[world], "world");

slab[world] = "earth";
assert_eq!(slab[world], "earth");

最初にSlab::new()でインスタンスを作成します。
slab.insert()でデータをslabに登録します。このときの戻り値がkeyになり,hello変数やworld変数に格納されるみたいな感じです。

これがslabの基本的な使い方です。

vacant_entry API

keyinsertよりも先に欲しい場合は,Slab::vacant_entry()という関数を用いることができる。

let mut slab = Slab::new();

let hello = {
    let entry = slab.vacant_entry();
    let key = entry.key();

    entry.insert((key, "hello"));
    key
};

assert_eq!(hello, slab[hello].0);
assert_eq!("hello", slab[hello].1);

最初にslab.vacant_entry()から返されたインスタンスをentry変数に格納します。
そしてentry.key()でまずkeyを生成しておきます。
そのあとentry.insert()をする際に,先に取得しておいたkeyと一緒に値をメモリに割り当てて保管します。

Slab::with_capacity()

let mut slab = Slab::with_capacity(1024);

// ... use the slab

if slab.len() == slab.capacity() {
    panic!("slab full");
}

slab.insert("the slab is not at capacity yet");

前もってslabに割り当てる領域の大きさを定義しておくこともできます。
このサンプルのように,あらかじめ必要な大きさをきめておき,保管しているデータの量がキャパシティに達したらpanic!()を実行する,ということもできます。

まとめ

slabクレートは個人的にPollよりもとっかかりやすかったです。
型が絞られるなら可読性の向上にもつながると思ったので,積極的に使っていきたいです。

参考リンク

https://docs.rs/slab/0.4.2/slab/
https://raskr.hatenablog.com/entry/2018/04/22/175053
https://stackoverflow.com/questions/3770457/what-is-memory-fragmentation
https://k-onishi.hatenablog.jp/entry/2019/07/09/223222

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3