プログラムの呼び出し次ページへ

第 1 章 パフォーマンスの最適化

この章では、プログラムのパフォーマンスを最適化する手法について説明します。具体的な内容は次のとおりです。

ここで紹介する情報は、原則的にネイティブコードにコンパイルするプログラムが対象であり、特に明記していない限り中間コードは対象外です。

1.1 パフォーマンス向上のテクニック

ここでは、Server Express システムによって生成されるプログラムのネイティブコードを最適化するためのテクニックをいくつか紹介します。これらのテクニックを正しく活用すると、アプリケーションコードを軽量化し、パフォーマンスを高めることができます。なお、紹介するテクニックは原則的なものと理解してください。つまり、これらのテクニックを使用しなくても正しく動作するプログラムは開発できますが、最適なパフォーマンスが得られる可能性は低くなります。

Server Express で開発したプログラムは、移植性に関するいくつかの条件を満たせば、他の COBOL 環境でも動作します。

1.1.1 データ型

正しいデータ型の選択は、アプリケーションの処理効率、特に演算パフォーマンスを最適化するうえで重要です。データ型によるデータ格納形式の違いについては、『言語リファレンスを参照してください。それぞれのデータ型の特徴を次に示します。

1.1.2 手続き部の記述

ここでは、プログラムのサイズとパフォーマンスに影響を与える手続き部 (PROCEDURE DIVISION) の要素を明らかにし、これらの要素を最も効率的に使用する方法を示します。

原則的に処理が単純であれば、それだけ実行速度は上がり、コンパイル後のコードサイズも小さくなります。1 つの複雑な処理を記述する場合より、いくつかの単純な処理に分けて記述する方が、より良いパフォーマンスが得られることがあります。プログラムのサイズとパフォーマンスを最適化するうえで、望ましい手続き部の記述方法を次に示します。

1.1.2.1 算術演算

算術演算のパフォーマンスを最適化するためにも、常に最も単純な記述方法を選んでください。

1.1.2.2 英数字データの操作

英数字データの最も効率的な操作方法は次のとおりです。

1.1.2.3 表操作

表の最も効率的な操作方法は次のとおりです。

1.1.2.4 条件文

条件文の最も効率的な使用方法は次のとおりです。

1.1.2.5 論理演算

ビット単位での論理演算の実行には、多くの COBOL システムライブラリルーチンが使用可能です(詳細については、『拡張言語機能』を参照してください)。これらのルーチンを使用すると、ビット単位で AND や OR、XOR などの論理演算を実行できます。

コンパイラはこれらのルーチンの呼び出しを検出すると、可能であれば最適化を行います。最適化では、ランタイムシステムの呼び出しのかわりにインラインコードが生成されます。インラインコードとは、呼び出しを行わずに関数を直接実行するネイティブコードのことです。最適化が行われない場合は、汎用ランタイムルーチンが呼び出されます。

呼び出しの最適化は、データ長をリテラルで指定している場合に実行されます。

AND および OR の論理演算は、VALUE 句を使用して実行することも可能です。詳細については、『言語リファレンスを参照してください。

1.1.2.6 PERFORM 文

PERFORM 文は、ほとんどの処理で優れたパフォーマンスを発揮し、プログラムサイズの増加を抑制する手段としても効果的です。さらに、プログラム構造が保守しやすくなるという利点もあります。PERFORM 文の最も効果的な使用方法は次のとおりです。

1.1.2.7 CALL 文

各種の CALL 文の最も効率的な使用方法は次のとおりです。

1.1.2.8 パラメータ

連絡項目に多くの参照を行わないでください。連絡項目とは、連絡節で定義されている項目、CBL_ALLOC_MEM 割り当てメモリに設定されている項目、および EXTERNAL 定義されている項目などです。

連絡項目へのアクセスは、常に作業場所節で定義している項目へのアクセスより遅くなります。そのため、連絡節で定義している項目を頻繁に使用するようであれば、その項目をプログラムの呼び出し時に作業場所節の項目に転記することによってアクセス効率を改善できます。転記された項目は、呼び出し元プログラムに制御を戻すときに必要に応じて連絡節の項目に転記します。呼び出されたプログラムでは作業場所節の項目に転記された項目が一貫して使用され、連絡節内の項目は使用されません。

1.1.2.9 ファイルのソート

ファイルのソート処理で入力手続きおよび出力手続きを実装する場合には、効率的な手続きを作成することが大切です。入力手続きおよび出力手続きの処理効率が低いと、ソート処理がきわめて遅くなる可能性があります。

1.1.3 コンパイラ指令

ネイティブコードのプログラムのパフォーマンスは、さまざまなコンパイラ指令を使用して向上させることが可能です。ただし、一部の指令については、プログラムの動作を確認しながら慎重に使用する必要があります。

通常、プログラムをネイティブコードにコンパイルする際には、次の各指令を使用します。

NOALTER
ALIGN"4" (32 ビットシステムの場合)
ALIGN"8" (64 ビットシステムの場合)
COMP
NOBOUND
NOCHECK
NOCHECKDIV
NONESTCALL
NOODOSLIDE
NOQUAL
NOSEG
NOTRUNC

生成されるコードのパフォーマンスを重視する場合には、次の各項目も効果的です。

REMOVE "ROUNDED"
REMOVE "ERROR"
REMOVE "INITIALIZE"
REMOVE "CORRESPONDING"
REMOVE "THRU"
REMOVE "THROUGH"

これらの予約語を除去すると、プログラムで非効率的な構文が使用される事態を回避できます。

1.1.3.1 指令によるパフォーマンスの最適化

プログラムのパフォーマンスは、さまざまなコンパイラ指令を使用して向上させることが可能です。コンパイラ指令のデフォルトが、そのままパフォーマンス向上に有効な場合もありますが、パフォーマンスを優先するためにデフォルト値から変更すべき指令もあります。ここでは、後者の指令を紹介します。

ALTER 指令

パフォーマンスを重視するプログラムには、ALTER 文は使用すべきではありません。さらに、コードの生成を回避するため、NOALTER 指令を指定してコンパイルします。

BOUND 指令

BOUND は、表項目に領域チェックを実行する指令です。

NOBOUND を指定してコンパイルするとアプリケーションのパフォーマンスが向上し、サイズは抑制されます。この指令を指定しないと、コンパイラは表項目への参照を検出するたびに領域チェック用のコードを生成します。

テスト段階では BOUND 指令を使用し、プログラムが表領域外のデータを参照していないことを確認します。完成版のコンパイルでは NOBOUND を使用して、プログラムのパフォーマンスを向上させます。

BOUNDOPT 指令

次の 2 つの条件が満たされる場合には、BOUNDOPT 指令でプログラムのパフォーマンスを最適化できます。

BOUNDOPT を指定すると、USAGE DISPLAY 添字内の表サイズを超える桁は無視されます。たとえば、表のエントリ数が 100 未満の場合、PIC 9(3) の添字は PIC 9(2) と同様に扱われます。

USAGE DISPLAY の添字は、特に理由がない限り使用しないことをお奨めします。

COMP 指令

COMP 指令を使用すると、数値のオーバーフローのチェックが無効になり、非常にコンパクトで処理効率に優れたコードが生成されます。

COMP は、USAGE COMP で定義したデータ項目の演算方法を変更します。その結果、コードの処理効率は向上しますが、演算方法は ANSI 規格に準拠しません。

使用方法に注意して正しく活用すると、COMP 指令はプログラムのパフォーマンス向上に優れた効果を発揮します。

NESTCALL 指令

NESTCALL は、ネストしているプログラムの呼び出しを可能にする指令です。そのような呼び出しが不要であれば、NONESTCALL 指令を指定してください。その結果、生成されるコードのパフォーマンスがやや向上します。

TRUNC 指令

TRUNC 指令を指定すると、USAGE COMP で定義したデータ項目に切り捨て処理が必要かを判定するコードが生成されます。

COMP 型データ項目に対する切り捨て処理が不要であれば、NOTRUNC 指令を指定することによって、より効率的なコードを生成できます。

1.1.3.2 指令によるサイズの最適化

プログラムのサイズは、さまざまなコンパイラ指令を使用して最適化することが可能です。コンパイラ指令のデフォルトが、そのままサイズの最適化に有効な場合もありますが、サイズを最適化するためにデフォルト値から変更すべき指令もあります。ここでは、後者の指令を紹介します。

ALIGN 指令

ALIGN 指令は、01 レベルおよび 77 レベル項目の境界を指定します。この境界は、常に 2 のべき乗 (2、4、8 など) になります。32 ビットの COBOL システムでは 4 以上 (ALIGN"4")、64 ビットのオペレーティングシステムでは 8 (ALIGN"8") を指定してください。高めの値はパフォーマンスの面で有効ですが、データレコード間に使用されないスペースを増加させます。

1.2 不正確な演算結果の回避

浮動小数を含む算術演算では正確な演算結果が得られない可能性があります。これは、COBOL ではデフォルトで数値が丸められないためです。次に例を示します (この例の WS02 は COMP-2 型のデータ項目です)。

accept ws02
compute ws01 = ws02
display ws01

このプログラムで最初に 2.3 を入力しても、最後に表示される値は 2.29 になります。

値を丸めるには、ROUNDED 指定を指定する必要があります。上記の例を ROUNDED 指定を使用して書き直したコードを次に示します。

accept ws02
compute ws01 rounded = ws02
display ws01

FP-ROUNDING コンパイラ指令を使用すると、プログラム内のすべてのデータ項目に丸めや切り捨てが実行されるように指定できます。この指令の詳細については、『Server Express ユーザガイド』の『コンパイラへの指令』の章を参照してください。

1.3 浮動小数点の実装 (32 ビット/64 ビット COBOL システム)

Server Express は IEEE の浮動小数点規格に準拠しています。ここでは、Server Express の各浮動小数点型でカバーされる値の範囲と精度を示します。

1.3.1 値の範囲

COBOL の 2 つの浮動小数点バイナリデータ型でカバーされる値の範囲は次のとおりです。

COMP-1 8.43E-37 3.37E38
-8.43E-37 -3.37E38
COMP-2 4.19E-307 1.67E308
-4.19E-307 -1.67E308

注: Server Express の浮動小数点型は上記の範囲をカバーしますが、実際に使用できるのは 2 桁の指数のみです。


1.3.2 精度

データ型のサイズと有効桁数の関係を次に示します。

データ型
サイズ
有効桁数
COMP-1 4 バイト 6 〜 7
COMP-2 8 バイト 15 〜 16

1.3.3 外部項目とリテラル

コンパイラは浮動小数点リテラルを検出すると、メインフレーム環境との互換性を検証します。その結果、リテラル値が次の 2 つの範囲から外れている場合には、コンパイル時にエラーが発生します。

0.54 E -78 0.72 E +76
-0.54 E -78 -0.72 E +76

1.3.4 浮動小数の誤差

IEEE 規格に準拠する 2 進浮動小数は、次の要素から構成されます。

値がゼロ以外の場合は、指数から定数を差し引いた値が、仮数の開始桁の計算に使用されます。そのため、倍精度浮動小数 (COMP-2) は、仮数 (m) で次のように表されます。

1*(2**m) + mb0*(2**(m-1)) + mb1*(2**(m-2)) + mb2*(2**(m-3)) + ... + mb51*(2**(m-52))

各仮数ビット (この例では mb0 〜 mb51) は 0 または 1 です。単精度浮動小数 (COMP-1) 項目では 2 の指数部の最大値と最小値の差が 23 を超えた場合、COMP-2 項目では 52 を超えた場合に、精度の問題が生じる可能性があります。

たとえば、2**56 を掛け合わせる仮数ビットと 2**2 を掛け合わせる仮数ビットの組み合わせで表現される COMP-2 項目は、指数部の差 (56 - 2) が 52 を超えるため、近似値への変換が必要になります。この規則は、浮動小数の実装やハードウェアプラットフォームの違いにかかわらず共通です。また、浮動小数の内部格納形式は、オペレーティングシステムの種類によって異なる場合があります。詳細については、『言語リファレンスを参照してください。オペレーティングシステム間の内部格納形式の違いによって誤差が生じることもあります。

2 進浮動小数が表現できる数値は、符号の違いにかかわらず、常に 2 のべき乗とその組み合わせのみです。たとえば、10 進の小数は 1/2、1/4、1/8、1/16、1/32 など、2 のべき乗の分母を持つ分数を組み合わせた値で表現されます。そのため、0.625 (1/2 + 1/8) などの値は正確に表現できますが、それ以外は実際の値をごくわずか上回る (または下回る) 近似値で表現されます。整数も同様に、1、2、4、8、16 など 2 のべき乗の組み合わせで表現されます。そのため、625 (1 + 16 + 32 + 64 + 512) などの値は正確に表現できますが、それ以外は近似値で表現されます。

1.4 大規模なプログラムの扱い

Server Express システムでは、静的にリンクされたコードと動的にロードされたコードを実行することが可能です。静的にリンクされたコードとは、実行ファイルの一部としてプログラム内に組み込まれたコードのことです。また、動的にロードされたコードとは、実行ファイルとは別のファイルに格納されているコード、具体的には COBOL から呼び出し可能な共有オブジェクトや、呼び出し時のみロードされて実行される .int ファイル (または .gnt ファイル) のことです。

動的にロードされた COBOL プログラムの開発時には、利用可能なメモリが効率的に利用されるように配慮する必要があります。Server Express では、プログラムをいくつかの小さい部分に分け、COBOL の呼び出しメカニズムを活用することによって、コンピュータに搭載されている容量以上のメモリを使用するプログラムを作成し、実行することが可能です。詳細については、『プログラムの呼び出し』の章を参照してください。


Copyright © 2002 Micro Focus International Limited. All rights reserved.
本書、ならびに使用されている固有の商標および商品名は国際著作権法で保護されています。

プログラムの呼び出し次ページへ