【入門編】INDEX関数による文字列検索の機械語レベルの最適化 – PL/Iの基本構文とデータ制御実践ガイド

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

でも、どうぞご安心ください。怖がる必要は全くありませんよ。
今回は、PL/Iのちょっとユニークな「識別子のルール」に軽く触れつつ、基幹システムの裏側でぶっとんだ速さを叩き出す、`INDEX`関数と機械語(アセンブラ命令)の熱い関係について、どこよりも優しく、かつディープに紐解いていきます。

Javaの `indexOf()` や COBOL の `INSPECT` とはどう違うのか? メインフレームの心臓部で何が起きているのか? さあ、コーヒー片手に覗いてみましょう!

—

1. PL/Iの「予約語を持たない」という圧倒的な自由と優しさ

他の言語を触ったことがある人が最初に驚くのが、PL/Iの変数名の自由度です。
JavaやCOBOLには「予約語(Keyword)」というものがありますよね。例えば、`IF` や `READ`、`DATA` といったシステムがあらかじめ使っている言葉は、変数名(識別子)としては使えないのが常識です。

ところが、PL/Iの仕様書をめくると、こんなことが書いてあります。

> 「PL/Iには、真の意味での予約語が存在しない」

「えっ、じゃあ `IF` っていう名前の変数を作ってもいいの!?」と思いますよね。
結論から言うと、文脈によってコンパイラが「おっ、ここはIF文の命令だな」「お、こっちはユーザーが作った変数だな」と空気を読んで判断してくれます。

例えば、こんなコードが書けてしまいます。

1
/ 予約語を持たないPL/Iの自由すぎる世界 /
DECLARE IF FIXED(3,0); / 変数名に ‘IF’ を使っちゃう暴挙 /

IF = 100; / 変数 IF に 100 を代入 /

IF IF = 100 THEN / 最初のは命令のIF、2つ目は変数のIF! /
PUT SKIP LIST(‘変数IFの値は100です’);

……いや、実務でこんな紛らわしいコードを書いたら、コードレビューで先輩にこってり絞られますので絶対に真似しないでくださいね(笑)。
ただ、何が言いたいかというと、PL/Iはプログラマの記述をガチガチに縛るのではなく、「文脈(Context)」をコンパイラが高度に解釈してくれる、懐の深い言語だということです。

この「コンパイラの賢さ」は、これからお話しする文字列検索の最適化においても遺憾なく発揮されます。

—

2. 文字列検索の主役:`INDEX` 関数とは?

基幹システムのバッチ処理では、大量のレコード(例えば、数千万件の電文データや取引ログ)から特定のキーワードやエラーコードを探し出す処理が日常茶飯事です。

他の言語でお馴染みの検索処理を、PL/Iでは `INDEX` 関数を使ってこのように書きます。

1
/ INDEX関数の基本的な使い方 /
DCL TARGET_STR CHAR(100) INIT(‘IBM MAINフレーム PL/I SYSTEM’);
DCL SEARCH_KEY CHAR(5) INIT(‘PL/I’);
DCL POS FIXED BIN(31);

/ 文字列の中からキーワードの位置を探す /
POS = INDEX(TARGET_STR, SEARCH_KEY);

IF POS > 0 THEN
PUT SKIP LIST(‘見つかりました! 位置=’, POS);
ELSE
PUT SKIP LIST(‘見つかりませんでした’);

Javaの `indexOf()` や COBOL の `UNSTRING` / `INSPECT` と使い勝手はほぼ同じですね。
「ふーん、左から何番目にあるかを返すだけの普通の関数ね」と思ったそこのあなた。実はこの裏側で、IBMメインフレームのハードウェア(CPU)を極限まで唸らせる、とんでもない職人芸が繰り広げられているのです。

—

3. 幕の内側:INDEX関数とTRT命令の秘密

JavaやC言語で文字列の検索処理を書くとき、私たちはどう実装するでしょうか?
大抵は `for` ループを回し、1文字ずつ比較していく「O(NM)のナイーブなアルゴリズム」になりがちです。それを愚直にやると、巨大なメインフレームのCPUであっても、文字数が数百万件に膨れ上がった瞬間に悲鳴を上げてしまいます。

しかし、IBMのSystem/360アーキテクチャ(およびその子孫である現代のz/Architecture)には、この文字列検索を爆速で処理するための専用のハードウェア命令(マシン語)が備わっています。

その代表が、`TRT`(Translate and Test:変換およびテスト)命令です。

TRT命令ってなに?

TRT命令は、アセンブラの世界では超有名な「テーブル引きと条件一致の判定を1サイクルでこなす怪物命令」です。
通常、文字列の中から「特定の文字のどれか」を探す場合、TRT命令を使うと、CPUのハードウェア回路がダイレクトにメモリをスキャンし、一致するバイト(文字)を見つけた瞬間にピタッと止まってくれます。

PL/Iコンパイラ(IBM Enterprise PL/Iなど)は非常に優秀です。私たちがソースコードに `INDEX(TARGET_STR, SEARCH_KEY)` と書くだけで、コンパイラは「おっ、このパターンならループを回すより、ハードウェアのTRT(またはそれに類する高速スキャン命令)を直接吐き出したほうが100倍速いな!」と自動的に判断し、機械語レベルでの最適化(ハードウェアアクセラレーション)を行ってくれます。

つまり、私たちが書いた高級言語のシンプルな1行は、コンパイラの魔法によって、IBMメインフレームのCPUが持つ最も効率的なハードウェア命令へとダイレクトに翻訳されているのです。

—

4. 実務で役立つ!効率的なデータ宣言と注意点

この爆速の `INDEX` 検索の恩恵を最大限に受けるためには、PL/I側のデータ宣言(ストレージ属性)にも少しだけ気を配る必要があります。

PL/Iで文字列を扱うときは、主に `CHAR` 型を使いますが、ここには2つの大きな違いがあります。

1. `CHAR(n) VARYING`(可変長文字列)

  • 文字列の実際の長さが変動するもの。内部的には「長さのヘッダ(2バイト)」+「実データ」という構造になります。

2. `CHAR(n)`(固定長文字列 / パディングあり)

  • スペース(空白)で常に指定された長さに埋め尽くされるもの。

実は、固定長 (`CHAR(n)`) 同士の検索であれば、ハードウェアのレジスタ操作やメモリスキャンと完全に同期しやすいため、コンパイラはさらにアグレッシブな機械語の最適化を行います。

実務のバッチプログラムで大量データを高速処理させたい場合のサンプルコードを見てみましょう。

1
—————————————————

  • 大量データからの高速コード検索サンプルバッチ

—————————————————
TEST_SEARCH: PROC OPTIONS(MAIN);

/ 1. 宣言部:固定長で綺麗にアライメントを揃える /
DCL RECORD_BUF CHAR(4096) STATIC; / 4KBの固定長レコードバッファ /
DCL ERR_CODE CHAR(4) INIT(‘ERR9’);
DCL FOUND_POS FIXED BIN(31);

/ 2. ファイル読み込み等のダミー処理(イメージ) /
/ READ FILE(INFILE) INTO(RECORD_BUF); /

/ 3. INDEX関数による超高速パターンマッチング /
/ コンパイラが最適化し、CPUのハードウェア命令が火を噴く瞬間です /
FOUND_POS = INDEX(RECORD_BUF, ERR_CODE);

IF FOUND_POS > 0 THEN
DO;
PUT SKIP LIST(‘エラー検出! オフセット位置:’, FOUND_POS);
/ エラー処理ルーチンへ… /
END;
ELSE
DO;
PUT SKIP LIST(‘正常レコードです’);
END;

END TEST_SEARCH;

このように、余計な自前ループを書かず、PL/Iのビルトイン関数(`INDEX`)に処理を丸投げすること。これが、メインフレームの性能を限界まで引き出すシステムアーキテクチャの極意です。

—

まとめ

いかがでしたでしょうか?
「予約語を持たない自由すぎる構文」を持ちながら、その裏側では「ハードウェアの限界性能を引き出す鬼のような機械語最適化」をサラッとやってのける。それがPL/Iという言語の、たまらなくシブくて魅力的なところです。

「レガシーシステム」と聞くと、古臭くてとっつきにくいイメージがあるかもしれませんが、こうして機械語やハードウェアの文脈まで掘り下げていくと、現代のモダンな言語よりもはるかに合理的で、美しい設計思想に感動させられます。

怖がる必要は全くありません。一つひとつの仕様を紐解いていけば、PL/Iはあなたの最高の相棒になってくれますよ。
それでは、次回のメインフレーム・アーキテクチャ解説でお会いしましょう!

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