【2020/10/24 一部追記】
名前付きパイプの利用
USS(Unix System Service)の階層型ファイル・システムによって、FIFO特殊ファイルを利用することができます。FIFO特殊ファイルは、「名前付きパイプ」とも呼ばれるプロセス間通信に使われる仕組みの1つです。z/OSのUSSでは、MVSバッチ・ジョブもこのFIFO特殊ファイルを使用することができ、次の図に示すような処理を同時に実行させることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//JOBA JOB (acct),CLASS=A,MSGCLASS=A //* //STEP1 EXEC PGM=IEBDG //SYSPRINT DD SYSOUT=* //SYSUT2 DD PATH='/u/batch/hfs1/test.pipe1', // DSNTYPE=PIPE,PATHDISP=(KEEP,DELETE), // PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU, // RECFM=FB,LRECL=128,BLKSIZE=32640 //SYSIN DD * DSD OUTPUT=(SYSUT2) FD NAME=F1,LENGTH=03,STARTLOC=01,PICTURE=3,'SEQ' FD NAME=F2,LENGTH=07,STARTLOC=04,FORMAT=ZD,INDEX=1 FD NAME=F3,LENGTH=01,STARTLOC=11,PICTURE=1,'-' FD NAME=F4,LENGTH=99,STARTLOC=12,FORMAT=AL,ACTION=RP CREATE NAME=(F1,F2,F3,F4),FILL='<',QUANTITY=1000000 END // // //JOBB JOB (acct),CLASS=A,MSGCLASS=A //* //STEP2 EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD PATH='/u/batch/hfs1/test.pipe1', // DSNTYPE=PIPE,PATHDISP=DELETE, // PATHOPTS=(ORDONLY,OCREAT),PATHMODE=SIRWXU, // RECFM=FB,LRECL=128,BLKSIZE=32640 //SYSUT2 DD SYSOUT=* //SYSIN DD DUMMY // // |
FIFOファイルの使用は簡単です。バッチ・ジョブのDDステートメントでは、DSNではなくPATHパラメーターを指定します。USS内ファイルのパス名の他に、DSNTYPE=PIPEを追加で指定すれば名前付きパイプになります。FIFOファイルを利用すれば、書き込み側ジョブと読み込み側ジョブのいずれが先に実行されてもかまいません。読み取り側が先に実行されても、書き込み側がレコードを書き込むまでは読み取り側のREAD動作で待ち状態になります。このサンプルでは、どちらが先に実行されてもいいように、どちらのジョブのFIFOファイルのPATHOPTSにもOCREATオプションを指定しています。(先に走った方がFIFOファイルを作る)
1 2 3 |
IGD17502I CREATION OF SPECIAL HFS FILE FAILED, RETURN CODE IS (00000075) REASON CODE IS (05580075) FILENAME IS (/u/batch/hfs1/test.pipe1) |
FIFOファイルに書き込むジョブと読み込むジョブが同時に実行された場合、タイミングによっては片方がファイル作成エラーでJOB Failedになる場合があります。回避するには、読み取り側のジョブを書き込み側ジョブがスタートしてからサブミットするか、SCHEDULEステートメントを定義して何秒間か実行開始を保留します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//JOBB JOB (acct),CLASS=A,MSGCLASS=A // SCHEDULE HOLDUNTL='+00:00:01' //* //STEP2 EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD PATH='/u/batch/hfs1/test.pipe1', // DSNTYPE=PIPE,PATHDISP=DELETE, // PATHOPTS=(ORDONLY,OCREAT),PATHMODE=SIRWXU, // RECFM=FB,LRECL=128,BLKSIZE=32640 //SYSUT2 DD SYSOUT=* //SYSIN DD DUMMY // // |
ISPFエディターからサブミットするなどの非定型処理であればサブミットのタイミングをずらすのは容易ですが、定型業務ジョブであればサブミットのタイミングをずらすよりは、予め空のFIFOファイルを作成しておき、ジョブ終了後も削除せずに残しておくも方法もいいでしょう。
1 2 3 4 5 |
//ALLOCATE EXEC PGM=IEFBR14 //FIFOFILE DD PATH='/u/batch/hfs1/test.pipe1', // DSNTYPE=PIPE,PATHDISP=(KEEP,KEEP), // PATHOPTS=(OWRONLY,OCREAT),PATHMODE=SIRWXU // |
UNIXファイルもMVSデータセット(順次や区分など)同様に、IEFBR14を実行してDDステートメントの機能だけで新規ファイルを作成することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//JOBA JOB (acct),CLASS=A,MSGCLASS=A //* //STEP1 EXEC PGM=IEBDG //SYSPRINT DD SYSOUT=* //SYSUT2 DD PATH='/u/batch/hfs1/test.pipe1', // PATHOPTS=(OWRONLY), // RECFM=FB,LRECL=128,BLKSIZE=32640 //SYSIN DD * DSD OUTPUT=(SYSUT2) FD NAME=F1,LENGTH=03,STARTLOC=01,PICTURE=3,'SEQ' FD NAME=F2,LENGTH=07,STARTLOC=04,FORMAT=ZD,INDEX=1 FD NAME=F3,LENGTH=01,STARTLOC=11,PICTURE=1,'-' FD NAME=F4,LENGTH=99,STARTLOC=12,FORMAT=AL,ACTION=RP CREATE NAME=(F1,F2,F3,F4),FILL='<',QUANTITY=1000000 END // // //JOBB JOB (acct),CLASS=A,MSGCLASS=A //* //STEP2 EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD PATH='/u/batch/hfs1/test.pipe1', // PATHOPTS=(ORDONLY), // RECFM=FB,LRECL=128,BLKSIZE=32640 //SYSUT2 DD SYSOUT=* //SYSIN DD DUMMY // // |
事前にFIFOを割り振っておけば、実行タイミングによる同名ファイル2重作成のエラーは起きません。PATHDISP(省略可能)やPATHOPTSの指定もシンプルです。
JES2のJEC(JOB Execution Controls) を利用することで、並行処理可能なステップをジョブに分割し易くなっています。名前付きパイプの機能と組み合わせれば、データの依存関係にあるジョブであっても同時に実行することができます。USSのFIFO特殊ファイル(名前付きパイプ)の利用は、バッチ処理パフォーマンスを向上させる有用な方法の1つです。
実際の効果
レコード数 | 書き込み→読み込みの縦列処理 | 書き込みと読み込みの並行処理 | 処理効率 |
---|---|---|---|
300万レコード | 約4秒(3~4秒) | 約2秒(1~2秒) | △50% |
500万レコード | 約5秒(5~5秒) | 約3秒(2~3秒) | △40% |
1000万レコード | 約10秒(9~10秒) | 約5秒(5~5秒) | △50% |
IBM Z14(3906-M04:z/VM Guest)でのバッチ・ジョブ実行時間の実測結果です。以前にzEC12(2827-H43:z/VM Guest)システムでも計測しましたが、いずれも2つのジョブ・ステップを順番に実行した時に比べて4割から5割の時間が削減されています。2つのステップを順番に実行したときの実行時間を1とすれば、それぞれのステップをジョブに分割して同時に実行した場合は、約0.5~0.6程度の実行時間で終了しています。
テスト用のz/OSシステムで関連するジョブだけを実行しているので遅延はほとんどありませんが、実働のシステムでは他にも沢山のジョブが同時に実行されるので遅延時間も加算されます。しかし、順番での実行であっても並行しての実行であってもシステム状況による遅延は同様に発生しますから、相対的な速度差が大きくぶれるようなことはないでしょう。
名前付きパイプを利用すれば、先行処理で書き出したデータ・レコードを即座に後続処理で読み出すことができます。結果として両方の処理が並行して実行できるので合計の処理時間は大幅に短縮されます。プログラムの修正などをすることなく、JCLとジョブ・スケジューリングの見直しでバッチ処理の効率向上を図ることができます。
FIFO特殊ファイル(名前付きパイプ)は、USSの階層型ファイルシステム内に作成されます。利用するには、その前提である階層型ファイルシステムについて概要と使い方を知っておく必要があります。USSの階層型ファイルシステムについては、「z/OS UNIXファイルシステム」や「バッチ・ジョブから階層型ファイル・システムを使う」の記事でも解説しています。
なお、名前付きパイプの機能は、USS(Unix System Service)の階層型ファイルシステムによるFIFO特殊ファイルとは別に、IBMのプログラム製品である「BatchPipes for OS/390」(*1)によっても利用できます。20年以上も前から提供されているもので、実際に導入し利用しているユーザーもいるでしょう。BatchPipesが導入されている場合は、そちらを使うことで名前付きパイプの機能を利用できます。ただし、BatchPipesは有償のプログラム製品です。利用状況のモニタリングやパフォーマンス・チューニング等、有償製品のBatchPipesは機能的にも豊富ですが、z/OS単体で利用できるUSSのFIFO特殊ファイルであれば容易に試して効果の検証を行うことができます。
*1 2000年に当時のOS/390向けに最後のバージョンが出荷された以降エンハンスはされていないが、現在のz/OS V2でも同製品が継続して出荷されている。