PL/Iの「予約語なき設計」とBUFFERED/UNBUFFEREDの深い淵
長年メインフレームの深淵でPL/Iと格闘してきた私だが、いまだに新進気鋭のJavaやC#エンジニアから「PL/Iにはなぜ予約語がないのか」と問われることがある。彼らにとっては、構文解析の容易さが言語の正義なのだろう。しかし、PL/Iの設計思想は「プログラマの意図をコンパイラに極限まで委ねる」という、ある種の哲学に基づいている。
識別子(変数名)として`IF`や`THEN`を使えてしまうこの仕様は、一見すると狂気の沙汰だ。しかし、コンパイラはコンテキスト(文脈)からその真意を読み解く。この「文脈依存性」こそが、PL/IがOS/390やz/OSの複雑なI/Oサブシステムと密接に結合できる理由であり、同時に、マイグレーション時に我々アーキテクトを悩ませる最大の要因でもある。
今回は、基幹バッチの性能を左右する「SEQUENTIALファイルのバッファリング戦略」について、現場の勘所を解き明かそう。
—
BUFFERED vs UNBUFFERED:I/Oの「呼吸」を制御する
基幹システムにおいて、ファイル入出力の性能はボトルネックの筆頭だ。PL/IのSEQUENTIALファイル宣言における`BUFFERED`属性と`UNBUFFERED`属性の差異は、単なるバッファの有無ではない。それは、「レコードが物理的にどこに存在するか」というOSとの約束事なのだ。
1. BUFFERED属性:OSへの一任と最適化
`BUFFERED`を指定すると、データ転送はOS(QSAM/BSAM)のバッファ管理に委ねられる。システムはブロック単位で読み込み、プログラムはバッファ上のレコードを順次参照する。
- メリット: 物理I/O回数の劇的な削減。
- リスク: レコード更新(REWRITE)時の競合。バッファ上のデータと実際の物理ディスクの同期タイミングがOS任せになるため、オンライン処理との混在環境では予期せぬ排他エラーを招く。
2. UNBUFFERED属性:ダイレクトな制御
`UNBUFFERED`は、プログラムが直接レコードの物理的な位置を意識することを許す。
- 運用例:
1
/ UNBUFFERED属性の宣言例 /
DCL IN_FILE FILE RECORD SEQUENTIAL UNBUFFERED;
/ レコード更新時のポインタ操作 /
DCL PTR PTR;
LOCATE RECORD_AREA FILE(IN_FILE) SET(PTR);
/ ここでポインタを操作し、直後にREWRITEすることで排他制御を厳密化 /
REWRITE FILE(IN_FILE);
アーキテクトとして忠告したいのは、「更新頻度の高いマスター更新処理では安易にBUFFEREDを使わない」ということだ。特にCICS連携やDB2と同時進行するバッチでは、バッファリングのタイムラグがデッドロックやデータ不整合の遠因となる。
—
マイグレーションの罠:内部データ表現とアベンドの解析
Java等への移行時、最も悲劇的なのは「パックデシマル(PIC S9(7)V99 COMP-3)」の扱いを甘く見た時だ。PL/Iでは符号ビット(`0xC`, `0xD`, `0xF`)が正しく制御されている前提で計算が行われるが、バイナリデータとして移行した際に符号ビットが化けると、演算時に「S0C7(データ例外)」でシステムが停止する。
現場で役立つダンプ解析の着眼点
S0C7が発生した際、コンパイラの最適化によってレジスタ上の値が元のソースコードの変数名と乖離することがある。そんな時は、コンパイラオプション `LIST` や `MAP` を付加して生成されたリストを出力し、「オフセット」と「命令コード」を照らし合わせるべきだ。
特に `DCL P PTR;` を多用し、ベース変数(`DCL X BASED(P) …`)でメモリを動的に切り替えるような設計(いわゆる可変長レコードのストラクチャマッピング)は、Javaのオブジェクト指向設計へそのまま移植できない。ここをどう「不変なデータ構造」に落とし込むか。それがアーキテクトの腕の見せ所となる。
—
結論:技術の橋渡しとしてのアーキテクト
PL/Iのコードを眺めていると、当時の先人たちが限られたCPUサイクルとメモリの中で、いかに「効率」と「信頼性」を両立させようとしたかの熱量が伝わってくる。
- 動的メモリ管理: `ALLOCATE`によるヒープ操作は、現代のガベージコレクションとは全く異なる「寿命管理」が必要だ。
- 埋め込みSQL: `EXEC SQL`を処理するプリコンパイラが生成するコードを一度覗いてほしい。そこには、PL/Iの構造体とDB2のホスト変数をマッピングするための、無骨だが完璧なロジックが隠されている。
もし、今あなたがPL/Iからの脱却を検討しているなら、言語の表面的な構文を変換するツールに頼ってはいけない。その裏にある「I/Oの挙動」や「データの物理配置」というアーキテクチャの本質を読み解き、新しいプラットフォームでそれをどう再現するか。
それが、レガシーを「歴史」として適切に昇華させる唯一の道であると、私は確信している。
次に執筆する機会があれば、次は「PL/Iコンパイラによる最適化でなぜループの境界条件が狂うのか(最適化レベルの深い闇)」について掘り下げてみようと思う。現場からは以上だ。
