MENU

静的プロシージャーによるパフォーマンス向上 ~連載|RPG Ⅳの魅力と可能性◎第3回 

 今回で3回目の連載となります。1回目ではフリーフォーム、2回目では日付計算について話をしました。どちらもコーディングレベルでの話ですので、コーディング、すなわち開発が差し迫っていない方にはあまり魅力的ではなかったかもしれません。今回はコーディングレベルだけでなく、パフォーマンスにも多大な影響を及ぼす話をいたします。これまでも時々登場した言葉で、ILE、統合化言語環境(Integrated Language Environment)についてです。

 統合化言語環境とは、異なる言語で書かれたモジュールを組み合わせ、1つのプログラムとして実行できるものであると、前々回に説明いたしました。システム開発において複数の言語を使うことがあるのかどうかの話はさておき、プログラム開発において、モジュール化、外部サブルーチンという考え方は、どの言語においても共通した考え方です。

 MAIN001は、データベース・ファイルTOKMSPを順次に読み取り、TOKMSP中のフィールド、TKBANGを外部プログラムのSUB001にパラメーターとして渡し、実行します図表1図表2。TKBANGは得意先番号で、SUB001はTKBANGを受け取り、該当する得意先番号のレコードをデータベース・ファイルJUMIDPから読み取り、受注金額を集計したのち、2番目のパラメーターフィールド、GOKEIに返します。

 

 

 呼び出し元のプログラム、MAIN001では集計した値を@ P 2で受け取り、集計した金額を元にしてこの後の処理が続いていきます。その後、次のTOKMSPのレコードが読み取られ、TOKMSPのすべてのレコードを読み終わるまで、処理は続きます。つまりSUB001は、TOKMSPのレコード件数分CALL(実行)されることになります。

 この場合、MAIN001もSUB001も、プログラムのコンパイル段階では、お互いの存在を確認する情報はまったく持ち合わせていません図表3。サンプルコーディングのCALL命令ではSUB001がどこのライブラリーなのかを示す情報もありませんので、CALLされた時点で初めてSUB001をライブラリーリストから探し出し、MAIN001から渡すパラメーターと、SUB001で受け取るパラメーターの順番とデータタイプをチェックします。パラメーターの桁数、データタイプ、順番がMAIN001とSUB001で違っていると、エラーになります。

 

 

 これらのチェックをすべて実行して初めてSUB001は主記憶域上にロードされ、SUB001の初期設定実行後、演算仕様書の命令を実行し始めます。このSUB001の実行プロセスは、MAIN001で読み込まれる得意先マスターファイルのレコード件数が1万件であれば、1万回行われることになります。

 この1万回のオーバーヘッドの発生は、MAIN001とSUB001が完全に別プログラム、別オブジェクトであることに起因します。SUB001の初期設定プロセスは、プログラム終了時にLR標識をオフのままRETRUN命令だけ終了することによって、再度SUB001がCALLされる際には前回終了したときと同じ主記憶域上の情報を再利用できるため、ある程度のオーバーヘッドの軽減は実現できますが、MAIN001からSUB001をCALLする際の、SUB001の場所、アドレス解決だけはどうにもなりません。

 ILE環境で実行されるプログラムは、コンパイル時にアドレスは決定済みです。プログラムがどこにあるのかがあらかじめわかっていれば、プログラムの実行が早いのは当然です。

 RPGⅢなどOPM(Original Program Model)でのプログラム開発環境は、1つのソースメンバーをコンパイルすれば、1つのプログラムができました。プログラムはオブジェクトタイプが*PGMとなり、5250画面のコマンド入力行からCALLコマンド、RPGプログラムからもCALL命令で実行されます。実はRPGⅣでも、CRTBNDRPGコマンドでコンパイルを行えば、*PGMのオブジェクトが作成され、手順そのものはOPMとさほど変わりはありません。

 しかしILE環境のプログラム作成手順では、ソースメンバーをコンパイルして、モジュールというオブジェクトを作成します(オブジェクトタイプは*MODULE)。このモジュールは通常のコンパイル同様に文法エラーをチェックし、文法エラーがなければ生成させるオブジェクトですが、*PGMのオブジェクトのように、CALLで実行可能な形式のオブジェクトではありません。実行可能なプログラムにするには、複数のモジュールを組み合わせてプログラムを作成する作業が必要です図表4

 

 

 つまり、OPMに比べてコマンドは1回多くなってしまうわけですが、1ソースメンバーからプログラムを作成する場合は前述のようにCRTBNDRPGを使うので、これらのコマンドを使わずともプログラムは作成できます。これらの作業が必要になるのは、MAIN001とSUB001を結合させ、1つのプログラムに結合する場合です。

 結合する場合、MAIN001のほうにロジックの変更が必要になります。SUB001を呼び出すロジックはCALL命令ではなく、CALLB命令を使用します。CALLBは静的プロシージャーの呼出し命令です図表5

 

 

 ここで初めてプロシージャーという用語が出てきました。プロシージャーとはILE環境でのプログラムの単位で、CALL命令や、5250画面でのCALLコマンドで実行することはできません。

 今回のケースですと、MAIN001、SUB001、ともにCRTRPGMODコマンドでコンパイルし、モジュールを作成します。次にCRTPGMコマンドで、MAIN001、SUB001を基にした、PGM001を作成します。CRTPGMコマンドでは作成されるプログラム名と、プログラムを構成するモジュール群、さらには入口点、つまり最初に実行されるプロシージャーを含むモジュール名をENTMODパラメーター指定します図表6

 

 

 PGM001は*PGMオブジェクトで、CALLコマンドで実行できます。PGM001がCALLされると、入口点となるプロシージャー、MAIN001が実行され、さらにMAIN001からバインドされたプロシージャー、SUB001が実行されます。SUB001がCALLされることはCRTPGMの段階で決定されているので、実行されるスピードはCALLで動的に呼び出されるプログラムのそれよりも速くなります。

 しかもILEのすごいところは、CRTPGMで結合されるプログラムが、RPGと、COBOL、C、CLプログラムでも可能だということです。そういう意味では、ほとんどのお客様が、RPGとCLを結合したILEプログラムを作成できる環境にあるといえるのです。

 今回のサンプルのMAIN001から呼び出されるSUB001はCLプログラムであってもよく(CLプログラムで今回の処理を実行できるかどうかは別として、単にCLプログラムが実行できるという意味です)、CLプログラムは、CRTCLMODコマンドで、モジュールを作成できます。このモジュールをCRTPGMコマンドで結合すればいいだけの話です。

 また、逆にCLプログラムからプロシージャーをCALLする場合、CALLコマンドではなく、CALLPRCコマンドを使用します。ここで注意しなければいけないのは、CALLPRCコマンドが使えるのはソース仕様タイプがCLPではなく、CLLEでなくてはいけないということです。通常、CLプログラム用のソースファイルQCLSRCは、ソース仕様タイプがほとんどCLPのソースメンバーですので、それとは区別するために、QCLLESRCなどのソースファイルを作り、CLLEメンバー専用のソースファイルにするとよいでしょう図表7図表8

 

 

 対話型プログラムのように、1画面で1プロシージャーを呼び出すような処理ではパフォーマンス改善はほとんど期待できませんが、膨大な件数のレコードを処理し、レコード単位で外部サブルーチンをCALLするようなプログラムであれば、このCALLBでの呼び出し、またはCLLPRCでの呼び出しをやってみる価値はあると思います。CALLBのほうが速いのですから、あえて遅いまま使い続ける必要はないでしょう。

 またILEにするからといって、すべてのアプリケーションをRPG ⅢからRPG Ⅳに移行する必要はありません。適用業務では*PGMのオブジェクトをCALLすればいいだけですから、RPGでできたプログラムであろうがCOBOLでできたプログラムであろうが関係ないとも言えます。いまRPG Ⅲをお使いの場合でも、一度にすべてRPG Ⅳに乗り換える必要はないのです。できるところから徐々に切り替えていってはいかがでしょうか。

 

 

著者|中村 潤 氏

株式会社アイ・ラーニング
IT研修本部 IBM製品研修部
ラーニング・アドバイザー

[i Magazine 2014年8月号掲載]

・・・・・・・・

◎ 連載|RPG Ⅳの魅力と可能性 目次

新着