【実務・中級編】CHARACTER(n) VARYINGの内部構造 – PL/Iの基本構文とデータ制御実践ガイド

メインフレームの深淵: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バイトの接頭辞を意識してソースコードを眺めてみてほしい。何か新しい発見があるはずだ。

タイトルとURLをコピーしました