導入
メインフレームのシステム開発において、ロードモジュールの肥大化やパフォーマンス低下は常に避けるべき課題です。特にPL/I等でプロシージャを定義する際、デフォルトのスコープ設定のままにしていませんか?プロシージャに「INTERNAL」属性を付与することは、単なる可視性の制御に留まりません。外部シンボルを抑制し、コンパイラによる高度な最適化を引き出すための、極めて重要な技術的プラクティスです。
基礎知識
メインフレームのリンケージにおいて、外部から参照可能なプロシージャは「外部シンボル」としてリンク・エディット時のシンボルテーブルに登録されます。これが肥大化すると、ロードモジュールのサイズが増加するだけでなく、リンク時間の増大や、実行時のロード負荷にも悪影響を及ぼします。
「INTERNAL」属性は、Javaにおける「private」修飾子と同等の概念です。この属性を付与されたプロシージャは、モジュール外部から呼び出せない「隠蔽された手続き」として扱われます。
実装/解決策
INTERNAL属性を付与することで、コンパイラは「このプロシージャはモジュール外から呼び出されることはない」と判断します。これにより、以下のメリットが得られます。
1. シンボルテーブルの削減:外部参照テーブルが整理され、ロードモジュールが軽量化されます。
2. レジスタ最適化:呼び出し規約(リンケージ・コンベンション)を標準のOSインターフェースに合わせる必要がなくなるため、コンパイラが独自のレジスタ割り当てを行い、オーバーヘッドを最小化できます。
3. インライン展開の促進:外部からの干渉がないため、コンパイラが積極的にインライン展開を行い、呼び出しコストをゼロにできる可能性が高まります。
サンプルプログラム
以下は、INTERNAL属性を活用したPL/Iの記述例です。外部から呼び出される「API」となるプロシージャと、内部でのみ使用する「ヘルパー」プロシージャを明確に分離しています。
/ メインのエントリポイントは外部公開 /
MAIN_PROC: PROC OPTIONS(MAIN);
DCL VAL1 FIXED BIN(31) INIT(10);
DCL VAL2 FIXED BIN(31) INIT(20);
DCL RESULT FIXED BIN(31);
/ 内部ヘルパープロシージャを呼び出し /
RESULT = CALC_INTERNAL(VAL1, VAL2);
PUT SKIP LIST(‘RESULT IS: ‘ || RESULT);
/ 内部限定のプロシージャ:INTERNAL属性で最適化を促進 /
CALC_INTERNAL: PROC(A, B) RETURNS(FIXED BIN(31)) INTERNAL;
DCL (A, B) FIXED BIN(31);
/ 外部からアクセス不可。レジスタ渡し等の最適化が適用される /
RETURN(A + B);
END CALC_INTERNAL;
END MAIN_PROC;
応用・注意点
現場での移行や開発においては、以下の点に注意してください。
・設計の分離:既存のプログラムを修正する場合、まずはモジュール内の全てのプロシージャを調査し、「APIとして公開が必要か」を精査してください。外部から呼び出されないものは、原則すべてINTERNALを付与する方針で設計すると、モジュール全体の品質が向上します。
・デバッグ時の制約:INTERNALプロシージャは外部シンボルとしてテーブルに載らないため、ダンプ解析時にシンボル名での特定が難しくなる場合があります。トレース用モジュール等では注意が必要です。
・コンパイラ最適化オプション:INTERNAL属性の効果を最大化するには、コンパイルオプション(例:OPTIMIZE(2)や(3))と併用することが推奨されます。コンパイラが「どこから呼ばれるか」を完全に把握できるため、静的な最適化がより強力に機能します。

コメント