記事のターゲット
- Rustを学ぼうと思っている人(俺)
- 公式ドキュメントでいきなり出てきた「ゼロコスト抽象化」が何なのか気になっている人(僕)
- つまり他言語に比べてRustが勝っている点を一つでも自分の言葉で説明したい人(私)
ゼロコスト抽象化
Rustの公式ドキュメントに出てくるあまり一般的ではない単語です
文字通り コストがない(ゼロ)としている抽象化のことです
プログラミング的抽象化
現代でよく扱われる高級言語には抽象化の概念が実装されている事が多く、デザインパターンの殆どがこの抽象化をベースにしている内容が多数見られます
処理系・属性値などをブラックボックス化して、使用タイミングで具体化した動きに変えるような書きぶりです
その名の通り、ゆるふわで定義しておいてその定義に合わせた実装を用意する内容です
この文脈の「コスト」とは?
抽象化に対する追加のコスト と考えて良いでしょう
ここで「え?抽象化のコストってなんぞや?」と思われるかも知れません
主に抽象化に対するコストは メモリの動的利用 (動的ディスパッチ)です
golangでも関数の引数にinterfaceを指定した場合はメモリアロケーション、つまりは動的なメモリ割り当てが発生します
golangも型付き言語なので事前にメモリ確保領域は確定できそうですが、interfaceを指定すると「どれくらいメモリ確保したらええねん?」ってなるので動的にメモリ確保するしかなくなるわけですね
※ 正直、パフォーマンスがシビアに求められるようなシステムでない限りは意識する領域では有りません
コストが肥大化すると大規模な処理系でCPU使用率がGCの影響でスパイクしたり、メモリ使用量が瀑増するなどの影響があります
参考:実装言語を「Go」から「Rust」に変更、ゲーマー向けチャットアプリ「Discord」の課題とは
よくわからないという人は以下を踏まえてコストを理解すると良いと思います
メモリが使われていないことを検知する
少なからず検知のためのリソースを用意する必要があります
コストですね
使われていないメモリ領域を解放する
同じく確保していたメモリ空間を誰かが「使っていいよ!」と解放させる必要があります
コストですね
ゼロコスト?
「抽象化すればコスト無いんじゃん?!ヒャフー!」なんて思わないでください
あくまでも 抽象化に対する追加のコスト がゼロなので「抽象化してもしなくてもコストが変わらないよ」というニュアンスです
Rustはなぜゼロコストなのか?
言うならば抽象化を動的ディスパッチではなく デフォルトで静的ディスパッチにより実現するためです
静的ディスパッチでは抽象化したコードをコンパイル時に単相化、つまり それぞれの型の分だけコードを生成 します
人間がint用の関数・bool用の関数…と言った横展開をしているのと変わりがない状態です
コレならば型が明確なのでメモリの確保も動的に行う必要がありません!
なので 抽象化に対する追加のコスト がゼロなのです
まとめ
- Rustはゼロコスト抽象化である
- このコストは抽象化に対する追加のコストである
- ゼロコストの理由は静的ディスパッチを利用しているからである
参考
Goのインタフェースがパフォーマンスに及ぼす影響
ゼロコスト抽象化とは一体何なのか
Rustのゼロコスト抽象化の効果をアセンブラで確認