言語 RubyかC++か

シェルスクリプトは、もうイヤなんです。

ということで、言語を変えて全部書き直すわけですが、言語の選択がこの先に大きな影響をあたえるはず。


今の自分のスキル(CとPHPしかやったことないんですけど...)から考えて、C、C++RubyJavaが考えられます。

まず、JavaはVMが巨大なので、ネットワークブート時のtftpでの転送中に、データが破損して起動に失敗する確率が高くなってしまう。tftpはUDPで信頼性が低い。組み込み向けのJava VMもあるものの、メモリやCPUに制限は無いので、これもどうか。そもそもx86の組み込み向けJava VMってあるんだろうか?ライセンスの問題も絡む。

Cは、難しい...。バイナリのサイズや実行速度は圧倒的なものの、プログラミングが難しい。それに、自分のスキルアップのためには、ここでオブジェクト指向言語を選択しておきたい気分。


で、残ったのはC++Ruby。試しにブートパラメータをパースするプログラム(クラス)を両方の言語で作ってみました。

C++

ちなみに、C++は(も)初心者です。

#include <iostream>
#include <string>
#include <map>
#include <fstream>

namespace VIVER {

using namespace std;
typedef map<string,string> Parameter_t;

class Parameter
{
private:
        Parameter_t mParameters;

public:
        // コンストラクタ
        Parameter() {
        }
        // デストラクタ
        ~Parameter() {
                mParameters.clear();
        }

        void Parse(void) {
                string param;
                ifstream cmdline ("/proc/cmdline");
                string::size_type poseq;
                pair<Parameter_t::iterator,bool> ins;

                while (cmdline >> param) {
                        poseq = param.find_first_of('=');
                        if (poseq != string::npos) {
                                cout << "値付きパラメータ: " << param.substr(0,poseq) << " = " << param.substr(poseq + 1) << "\n";
                                // 値付きパラメータ
                                ins = mParameters.insert(
                                        Parameter_t::value_type(
                                                param.substr(0,poseq),
                                                param.substr(poseq + 1)
                                        )
                                );
                                if (!ins.second) {
                                        // キーが重複 -> 上書き
                                        mParameters[param.substr(0,poseq)] = param.substr(poseq + 1);
                                }
                        } else {
                                cout << "単発のパラメータ: " << param << "\n";
                                // 単発のパラメータ
                                ins = mParameters.insert(
                                        Parameter_t::value_type(
                                                param,
                                                "1"
                                        )
                                );
                                if (!ins.second) {
                                        // キーが重複 -> 上書き
                                        mParameters[param] = "1";
                                }
                        }
                }
                cmdline.close();
        }

        string GetValue(string key) {
                Parameter_t::const_iterator n = mParameters.find(key);
                if (n == mParameters.end() ) {
                        return "";  // 該当パラメータ無し
                } else {
                        return n->second;
                }
        }
}; // class Parameter

} // namespace VIVER

using namespace VIVER;

int main(void) {
        Parameter param;
        param.Parse();
        std::cout << param.GetValue("sata");
        return 0;
}

Ruby

Rubyも初心者。

#!/usr/bin/ruby

module VIVER

class Parameter
        def initialize
                @params = Hash.new
        end
        def parse
                begin
                        cmdline = File.open("/proc/cmdline")
                        cmdline.gets.split.each {|arg|
                                if /([^=]*)=(.*)/ =~ arg
                                        @params[$1] = $2
                                else
                                        @params[arg] = true
                                end
                        }
                        cmdline.close

                rescue => ex
                        print ex.message + "\n"
                end
        end
        def get(key)
                # keyが存在しなかったら戻り値はnil
                return @params[key]
        end
end  # class Parameter

end  # module VIVER


include VIVER

parameter = Parameter.new

parameter.parse
p parameter.get("vga")

どうする

明らかにRubyの方が短いし読みやすい。それに書きやすい。

バイナリのサイズ(共有ライブラリやインタープリタも含む)は、Rubyの方がすこし大きい。(C++は、libstdc++がかなり大きい)

実行速度は、コンパイラ型言語とスクリプト型言語のセオリーから言って、C++の方が速いはず。


うーむ...。Rubyかな。