【入門編】アライメント属性(ALIGNED / UNALIGNED)の影響 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいはビジネスチルドレンな言語をバリバリ書いてきた方にとって、IBMメインフレームの「PL/I(ピーエルアイ)」という名前を聞くだけで、なんだか冷や汗が出てきたり、「古めかしい要塞のような言語だ…」と身構えてしまったりしませんか?

大丈夫です、安心してください。怖がる必要は全くありませんよ。
今回は、PL/Iの数あるデータ制御の肝の一つ、「アライメント属性(ALIGNED / UNALIGNED)」について、他の言語との違いを交えながら、ふんわりと優しく紐解いていきたいと思います。

—

そもそも「アライメント」って何だろう?

JavaやCOBOLを触ってきた方なら、「変数を定義する=メモリにその分の箱が確保される」というイメージはお持ちだと思います。例えば「10桁の数字」や「整数型」を定義すれば、必要なサイズ分のメモリが割り当てられますよね。

しかし、IBMメインフレーム(基幹系を支える大型コンピューター)のCPUは、メモリからデータを読み書きするときに「キリの良いアドレス(境界)」が大好きという、ちょっとお茶目(かつ厳格)なこだわりを持っています。

  • 2バイトのデータなら、偶数のアドレスから読み書きしたい!
  • 4バイト(フルワード)のデータなら、4の倍数のアドレスから読み書きしたい!

この「CPUが喜ぶキリの良い位置にデータをきっちり整列させること」を ALIGNED(アラインド) と呼び、逆に「そんなキリの良い場所なんて気にせず、空いた隙間に詰めていこうぜ!」とするのが UNALIGNED(アンアラインド) です。

電車やバスの座席に例えてみましょう。

  • ALIGNED: 「1人分の席に、必ず1人ずつゆったり座る。通路側や窓側のキリの良い位置を陣取る」
  • UNALIGNED: 「空いている隙間があれば、そこにピタッと隙間なく体を滑り込ませる」

この違いが、メモリの「ストレージ効率(容量)」と「アクセス速度(パフォーマンス)」に大きな影響を与えるんです。

—

固定小数点数(FIXED BINARY / DECIMAL)におけるデフォルトの挙動

PL/Iの世界では、特に指定しない場合、データ型ごとにデフォルトのアライメント属性が決まっています。

例えば、固定小数点数である FIXED BINARY(二進固定小数点数) や FIXED DECIMAL(十進固定小数点数) を扱うとき、PL/Iは賢いので、何もしなくても最適な状態にしようとします。しかし、構造体(STRUCTURE)の中で複数のデータをまとめるときに、この属性が牙を剥く(あるいは救世主になる)ことがあります。

ちょっと実際のPL/Iコードを見てみましょう。大文字で書かれたいかにもレガシーなコードですが、日本語コメントで優しく解説するので安心してくださいね。

1
DCL 1 EMPLOYEE_REC ALIGNED,
2 EMP_ID FIXED BIN(15) UNALIGNED, / 社員ID:2バイト、隙間なく詰める /
2 EMP_AGE FIXED BIN(15) ALIGNED, / 年齢:2バイト、4バイト境界に合わせる /
2 EMP_SALARY FIXED BIN(31) ALIGNED; / 給与:4バイト、4バイト境界に合わせる /

おっと、いきなり見慣れないキーワードが出てきましたね。でも大丈夫です。
構造体全体としては `ALIGNED`(きれいに並べる)を指定しつつ、中の項目ごとに `UNALIGNED` や `ALIGNED` を混ぜ込んでいます。

—

ALIGNED と UNALIGNED、どちらを選ぶべき?

実務の現場でバッチプログラムの改修や、外部ファイル(COBOLのCOPY句から変換したデータなど)とのインターフェース設計をしていると、この2つの選択に頭を悩ませることがあります。それぞれの特徴を見てみましょう。

1. UNALIGNED(アンアラインド):ストレージの節約と互換性の王様

  • メリット: メモリやディスクの消費量を最小限に抑えられます。余計な「パディング(隙間)」を作らないため、COBOLの記録レイアウトや、外部から送られてきた電文データと1バイト単位でピタリと一致させやすいのが特徴です。
  • デメリット: CPUが「あれ?このデータ、キリの悪い中途半端なアドレスにあるぞ…」と気づいた瞬間、読み込みにほんの少し余分なCPUサイクル(手間)がかかることがあります。(※近年のメインフレームは優秀なので速度低下は微小ですが、仕様上の注意点です)

2. ALIGNED(アラインド):CPUが一番喜ぶ高速処理

  • メリット: CPUが最も得意とするメモリ境界にデータが配置されるため、アクセス速度が最速になります。大量のループ処理でガンガン計算を回すような数値データには最適です。
  • デメリット: データの間に「見えない隙間(パディング)」が勝手に挿入されることがあるため、構造体全体のサイズが意図せず大きくなったり、外部ファイルとのレイアウトズームの原因になったりすることがあります。

—

初学者がハマりやすい「落とし穴」とアドバイス

JavaやCOBOLから来たエンジニアが、PL/Iのマイグレーション案件で一番やらかしてしまうのが、「外部連携ファイルのレイアウト定義で、うっかりデフォルトのALignedが発動し、項目のオフセット位置がズレてしまうバグ」です。

COBOLにはアライメントという概念が基本的に存在せず、記述された順に隙間なくデータが並びます(※SYNC句を使わない限り)。しかし、PL/Iでは構造体や変数の定義方法によって、勝手にメモリのパディング(調整の隙間)が入ることがあるのです。

もしあなたが「他のシステムから受け取ったバイナリファイルをPL/Iでゴリゴリ読み込む」というプログラムを組む場合は、基本的には `UNALIGNED` を明示的に指定して、隙間風が入らないようにタイトに組むのが実務での定石です。

1
/ 外部ファイルや電文をマッピングする際の安全な書き方例 /
DCL 1 ACCOUNT_RECORD UNALIGNED,
3 ACC_NO FIXED BIN(31),
3 ACC_NAME CHAR(20),
3 ACC_BALANCE FIXED DEC(11,2);

このように、構造体全体の頭に `UNALIGNED` をドーンと指定してあげれば、中のメンバーも仲良く隙間なく並んでくれます。これならCOBOLのファイルレイアウトとも喧嘩せずに仲良く動いてくれますよ。

—

おわりに

いかがでしたでしょうか?
「アライメント属性(ALIGNED / UNALIGNED)」という言葉を聞くと、なんだか難しそうなハードウェアの低レイヤーの話に聞こえますが、要するに「データをきっちり整列させてスピードを重視するか、隙間なく詰めて容量と互換性を重視するか」という、お部屋の家具のレイアウト選びのようなものです。

レガシーなPL/Iの世界も、こうして背景や理由を一つずつ紐解いていけば、決して怖くありません。むしろ、ハードウェアの性能を極限まで引き出そうとした先人たちの知恵が詰まった、非常にロジカルで面白い仕組みであることが分かっていただけたのではないでしょうか。

日々のマイグレーションや保守作業でPL/Iと格闘するあなたの背中を、ほんの少しでも軽くできたなら幸いです。それでは、次回のレガシー探訪もお楽しみに!

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