mrubyから見る組み込み分野でのスクリプト言語に必要な要件とか


mrubyは組み込み向けと言われつつも、実際はそれほど要件を満たしていないのでは疑惑が個人的にあるので、それについて検討するだけの手抜きです。

動機

Elixir FountainというとりあえずRailsをdisっとけ感あるPodcastを延々と聞いてたのが原因な気がします。
(とりあえず、disっとけ感はあるんですが、Railsが問題を解決できてないのもよくないのでどっちもコロシアエーとしか思わないです。ていきゅうはいいですよ。ざーさんが声当ててます。たまに出てくるCV石原夏織さんもよいです。)
主に55回58回が刺激になりました。
Elixir(というかErlang)でも珍しい組み込み分野での言語がどうあるべきかを語っているのでとても参考になります。

Nerves Projectは、Elixirで組み込みソフトウェアを構築するというのもなかなか興味深いです。
Elixirを使うことで、ソフトウェアの更新を容易にしたり、Erlang VMを使って構築することで信頼性を向上させるようです。

組み込み環境で満たすべきかと思われる要件

まだまともに勉強が足らないのですが、まあ大体話を聞くと組み込み分野ではこれが必要と思われるものを3つ挙げておきます:

  • 低リソース性(低消費電力、低価格、低メモリ、CPU、電源)
  • ソフトウェアとしての信頼性(バグの入り込みづらさ、即応性、最悪ケースの想定)
  • 最悪必要になる計算資源量を見積もれるか(メモリ空間消費量、CPU実行時間)

mrubyは要件を満たしているか?

端的に言ってしまうと、他のRuby実装より比較的満たしているかと思います。
mruby/cは更に厳しい条件を想定して開発されているのでより満たしてはいますが、未実装部分を考えるとまだ実用には少し遠いかと感じてます。

低消費電力

組み込み言語だと、Luaの後塵を拝するしかないのでその時点でかなり弱い気がします。
LuaのAPIは不便ですが、総合的な性能などを鑑みるとLuaに開発効率以外は劣ります。

分野によってはLuaですら、リソースを消費しすぎるといった世界なのでもっと追求するべきかと思います。

また、メモリのフットプリントがまだ比較的大きいため必要なDRAMが多くなります。
普通のPCだとメモリの消費電力を無視してしまいがちですが、組み込み分野によってはそれも問題になってくるようです。
(コンピューターが稼働し続ける限り必要な時間あたりの固定費なのでなくせるものならなくしたいので当然かとは思います。)

信頼性

Address Sanitizerを使って出て来るmrubyのバグの多さを考えるとそれほど高いとはいえないかと思います。
(いちおう、そういったチェックがなされてるといった点では比較的よい点ではあるのですが、元の構造がどうしようもないところがあるので厳しいです。)

また、動的型付け言語の特徴としてテストを書かないことには信頼性が上がらないわけですが、現状

  • カバレッジがとれない(デバッグ情報やVM命令フックなど必要な部品自体はありますが、そもそも実装がない)
  • テストを書く体制がCRubyなどと比べて整っているとはいえない

のがつらいです。

そもそも、組み込み分野は弱いとはいえC言語という型付き言語で開発されるの主流と思われる世界ですが、そこで動的型付けを導入しても(開発効率以外は)信頼性の低下を考えるとそれほど恩恵がないです。
(場合によってはツールがほとんどない状況なのでC言語よりもデバッグ困難な状況に陥りかねないので微妙です。)
さらに、C++やRustなども使える状況を考えると弱い型や動的型付けな言語を選択する理由がそれほどないかと思います。
Elixir Fountain 58回でそういった部分を取り上げているので興味のある方は是非。)

即応性/リアルタイム性といった観点からもそれほどよくはないです。
現実の世界に近いところにあるコンピューターだと、すぐに処理を切り替えて割り込みを処理しないといけないわけですが、メモリ確保戦術にまだ問題があるため、割り込みを処理するためにメモリ確保処理が走ってしまうなどの問題が起きかねません。
最悪のケースだと、割り込み時にいきなりGCが走る、よくてメモリ確保なので、即応性からはとても問題があります。

最悪時に必要な計算資源量

参照カウントでないGCでメモリ管理を行う点から、無理を感じます。
GCの仕様自体が非決定的なため、組み込み分野で使うのには適切と思えないです。
GCを使っていい計算資源に余裕のある領域は何十年前くらいからずっと広がってはいるんですが、その領域にはCRubyとかがすでにあるので、mrubyの出るべき幕はあまりないかもしれません。

mruby/cでは開発者の方に軽く話を聞いた範囲だと、参照カウントベースのメモリ管理を実装しているようです。
参照カウントはよく間接的なメモリ管理(マークしていくようなGC)と比較されますが、循環参照に対する十分な対策を行えば必要資源量を見積もりやすいと思います。

Squirrelという言語では、普段の資源管理を参照カウントで行い、必要に応じてGCを使えるというとても賢い選択をしています。
GCを開発時に併用することで、循環参照に由来するバグを弱参照にすることで潰していくことができるので場合によってはリリース時にはGCが外されているといったことが可能になるようです。

実行時間の問題として、単一VM命令から普通に別のメソッド呼び出しが発生しかねないというのは命令同士の比重の差を考えると必要計算量の見積もりを困難にします。
何命令かを実行して処理を戻してほしいといったAPIを実装しても、たったの数命令のつもりがなかなか処理が戻ってこないといったことも起こりえます。
またmruby/cだと、そういった命令や処理が未実装だった気がします。
この点が即応性にさらに疑問を投げかけます。

また、動的型付けな点も計算資源量の見積もりを難しくします。
弱い型付けであるC言語ですらコンパイル時に確保するべきメモリ量を大体出せるわけですが、動的型付けな場合それですら実行時にしか決定できないケースもあります。
C言語では非常に煩雑になることをするとしても、個人的にスクリプト言語を避けたくなります。
(もちろん、そういった煩雑な部分をスクリプト言語で計算して、C言語のコードを生成するなら喜んでやります。)

雑な結論とか

mruby自体は、これまでCRuby環境を入れるほど余裕のない分野で実績や期待があるので上の部分を満たす必要は実際それほどないです。
サーバーサイドのミドルウェア分野における活躍などはめざましいものですし、設定記述の柔軟性でとても期待されています。

それでも、組み込み分野では使える計算機の性能は向上していますが、スクリプト言語を満足に動かせるかと言われるとまだ難しそうです。
本当に組み込み環境で利用するといったことを想定していくと3つの要件をより満たさないと実用に耐えうるか難しくなります。

個人的に

  • 強い静的型付け
  • より必要量を見積もりやすい決定的なメモリ管理
  • コンパイル時やビルド時の処理で実行時の計算を削減する

は、より広い分野での活用を考えると必須ではないかと思います。

近所の大きめの図書館で組込みシステム基礎技術全集をいうのがあったので、もうちょっと勉強します。