top pageへ.

Programming Room.

Programming Techniques.

メモリ効率の向上.

 PC用のアプリケーションを作るだけなら、メモリの安くなった現在ではほとんど気にすることのないメモリ効率。でも特定の目的や開発環境ではかなり、いやとっても重要なこと。
 メモリ(ROM/RAM)の無駄遣いを減らすためのコードの書き方。


おしながき


処理速度との関係.

言語依存なし 保守性 処理速度 メモリ効率 難易度

 処理速度に関するテクニックと、メモリ効率向上に関するテクニックが相関を持つ場合があります。相関の状態は主に次の3つだと思います。


if〜elseとswitch〜case〜defaultの使い分け.

C/C++言語 保守性 処理速度 メモリ効率 難易度

課題.

 条件分岐を記述する場合に、if〜else でも switch〜case〜default でもどちらでも使えることがあります。このような場合にはどちらを使うべきか悩むことになります。


改善案.

 以下のような基準で判断するのが良いと思います。


理由.

 このような判断基準を勧める理由は、switch文の方が可読性が良いというのが主な理由です。
 また、処理速度やメモリ効率を考慮しても上記の判断基準が有効です。if文を使用した場合は、ソースコードのコンパイル結果は、以下のように比較命令と条件分岐命令がif文の数だけ並ぶことになります。

/* C言語のソースコード */
    if (var1 == 1) {
        (処理1)
    } else
    if (var1 == 2) {
        (処理2)
    }
; アセンブリ言語のコンパイル結果
        cmp     [var1], 1       ; この2行が if (var1 == 1)
        jnz     value_is_not_1  ;
        (処理1)
        jmp     finish
value_is_not_1
        cmp     [var1], 2       ; この2行が if (var1 == 2)
        jnz     finish          ;
        (処理2)
finish

補足.

 switch文を使用した場合、対応するプロセッサの命令体系によって、生成されるコードが異なります。プロセッサがcaseキーワードに続く値と分岐先をセットにしたテーブルを検索して分岐先を決める、まさにswitch〜case〜defaultそのままの機能の命令を持っているなら、その命令が使われるでしょう。
 しかし現在のプロセッサの多くはそのようなswitch〜case〜defaultそのままの機能の命令などは持っていません。そのため多くのコンパイラはswitch〜case〜defaultに対して、case1つにつき1回の比較命令と条件分岐を生成し、それをcaseの数だけ繰り返すのが、一般的なようです。
 条件式(あるいはcase文)が2程度以上ならif文よりswitch文を使用した方が、処理速度やメモリ効率が良いと言われているのは、さまざまな有識者の経験的なものです。


定数データのconst修飾.

言語依存なし 保守性 処理速度 メモリ効率 難易度

課題.

 参照だけしか行わないテーブルなどのデータを配列変数で確保することはよくあります。その定義の仕方によりメモリを無駄に消費する場合があります。

 どちらの場合にも、1つの変数の定義に対して、変数の実体と初期値リストの2つが確保されることになります。本節で前提としているのは、変数の参照だけ行い値を変更することはない場合です。値を変更しないのに、値の変更が可能なように、データ領域に実体を確保しているのは無駄です。


改善案.

 静的変数の場合は、変数の定義にconst修飾子を記述することで解決します。

const   int     GlobalTable[8] = { 4, 3, 7, 8, 10, 17, 1, 0 };

void    func(void)
{
    static  const   int     table[8] = { 4, 3, 7, 8, 10, 17, 1, 0 };

 このように定義すると、変数の実体は定数領域(あるいはコード領域)に配置された初期値リストのみになります。変数の値の初期化のために、初期値を実体にコピーする必要もなくなるので、コピーのコードが消費していたメモリ(コード領域)とその実行時間も削減できます。
 つまり効果は、データ領域・定数領域・コード領域の削減、処理速度の若干の高速化となります。


注意.

 例ではよく使用されるケースとして配列変数を示しましたが、スカラ型変数でも同様です。

 最初の例のように変数をスタック上に確保されるローカル変数として定義していると、const修飾しても効果は得られません。静的に確保されるようにブロック外で定義するか、static記憶クラス指定子を併用する必要があります。


▲page top.
Copyright 2005-2016, yosshie.