メインフレームの深淵:VARYING属性と「2バイトの罠」を解き明かす
現場の若手から時折、「`CHARACTER(n) VARYING`って、結局普通の`CHARACTER(n)`と何が違うんですか? 便利そうだから全部VARYINGでいいですよね?」という質問を受けることがある。
結論から言えば、「安易なVARYINGの多用は、基幹バッチの性能を殺す」。
今日は、IBMメインフレームの心臓部でPL/Iがどう文字列を扱っているのか、その内部構造とパフォーマンスへの影響について、実務の視点から紐解いていこう。
—
1. 内部構造:2バイトの「長さ情報」という名の番人
`CHARACTER(n)`が固定長であるのに対し、`CHARACTER(n) VARYING`は、宣言した最大長(n)に加えて、文字列の現在長を格納するための2バイト(Halfword)の接頭辞を内部的に付与する。
例えば、`DCL NAME CHAR(10) VARYING;` と宣言した場合、メモリ上には計12バイトが確保される。
- 先頭2バイト:現在の文字列長(Binary Halfword)
- 残りの10バイト:実際のデータ領域
この「先頭2バイト」の存在が、文字列操作において非常に重要になる。コンパイラは、代入や連結(`||`)、あるいは`SUBSTR`関数などのBUILTIN関数を呼び出すたびに、この先頭2バイトを読み取り、現在の長さを判定してから処理を行う。固定長のようにオフセット計算だけで完結せず、常にメタデータの参照が発生するのだ。
—
2. 実践:VSAM入出力とVARYINGの相性
VSAMファイルや順次データセットへ書き出す際、`VARYING`変数をそのまま`WRITE`文に放り込んでいないだろうか?
もしそのまま出力すると、先頭の2バイトの長さ情報もデータの一部としてファイルに書き込まれてしまう。これに気づかず、後続のプログラムが読み込んで「先頭にゴミがついている!」とパニックになるケースは、この業界の登竜門的トラブルだ。
以下のコード例を見てほしい。
1
/ ————————————————————- /
/ VARYING変数の安全な取り扱い例 /
/ ————————————————————- /
TEST_PROC: PROCEDURE OPTIONS(MAIN);
DCL MSG_VAR CHAR(50) VARYING;
DCL FIX_REC CHAR(50);
MSG_VAR = ‘BATCH_PROCESS_COMPLETED’;
/ VARYINGの長さ情報を意識した処理 /
/ 不要な空白を削るTRIM関数と併用するのが定石 /
FIX_REC = TRIM(MSG_VAR);
/ VSAMへの書き込み時は必ず固定長へ変換する /
WRITE FILE(SYSUT1) FROM(FIX_REC);
/ 文字列操作時はBUILTIN関数を活用する /
IF LENGTH(MSG_VAR) > 0 THEN DO;
PUT SKIP LIST(‘データ長:’ || TRIM(CHAR(LENGTH(MSG_VAR))));
END;
END TEST_PROC;
—
3. パフォーマンスとONユニットの制御フロー
なぜ、高頻度で実行されるバッチ処理で`VARYING`を乱用してはいけないのか。それは「動的なメモリ再配置のオーバーヘッド」に尽きる。
文字列の長さが頻繁に変わる処理を行うと、PL/Iの実行時ライブラリは内部的にメモリの切り詰めやコピーを繰り返すことになる。特に、何百万件というレコードを扱うループ内で`VARYING`の連結を繰り返すと、CPU時間は確実に増大する。
また、デバッグ時や例外処理において注意したいのが`ON`ユニットだ。`VARYING`の範囲を超えた代入を行った場合、`STRINGRANGE`条件が有効であれば`ON STRINGRANGE`が発火する。
1
/ 文字列の境界チェックを行うデバッグ手法 /
ON STRINGRANGE BEGIN;
PUT SKIP LIST(‘警告: 文字列の長さが定義域を超えました’);
END;
/ REORDERオプションを付けた最適化コンパイル時は /
/ 実行時チェックが省略されることが多いので注意が必要 /
—
4. 現場のアーキテクトからの助言
私が大規模マイグレーションの現場で設計を行う際は、以下の基準で使い分けている。
1. 外部インターフェース(ファイル入出力・DB): 原則として`CHARACTER(n)`の固定長を使用する。データ構造の確定は性能安定化の要である。
2. プログラム内部のワーク変数: 文字列加工が頻繁に発生し、かつ最大長が予測できない場合にのみ`VARYING`を許可する。
3. パフォーマンスのボトルネック調査: 処理速度が遅いバッチがあれば、まず`VARYING`の多用箇所を疑え。固定長への置換だけで劇的に改善することは珍しくない。
`VARYING`は便利な道具だが、メインフレームという過酷な環境では、その利便性の裏にある「コスト」を常に意識しなければならない。
「コンパイラが裏で何をやっているか」を想像できる力こそが、この先も君を支える強力な武器になるはずだ。次の改修でも、その2バイトの接頭辞を意識してソースコードを眺めてみてほしい。何か新しい発見があるはずだ。
