
本記事は、グローバルアクセスとグローバル・バッファの動作について解説致します。
Q. 2回目の実行は何でこんなに早いの?
A. 1回目に実行したグローバルが、メモリ上にキャッシュされるため。
実際に速度を検証してみましょう。
下記処理をターミナル上で2回実行してみます。
ClassMethod blockCheck()
{
s start = $zh
// No.29842 データ・ブロックより
s txt = ^BlockSearch(1)
s txt = ^BlockSearch(2)
// No.465390 データ・ブロックより
s txt = ^BlockSearch(162820)
s txt = ^BlockSearch(163022)
// No.29842 データ・ブロックより
s txt = ^BlockSearch(203)
w $zh-start
}
グローバル・バッファを削除するため、一端IRISを再起動してからターミナルで実行します。
処理結果を見てみると、2回目は1回目と比較して、およそ1,000倍速く処理が完了しています。
この結果だけを見ると、実に驚異的な速度差にですよね。
この速度差は、1回目の処理でメモリ上にグローバルがキャッシュされた事が要因となっています。
本記事では、このグローバル・バッファについて解説したいと思います。
グローバルのキャッシュはブロック単位
ObjectScriptではグローバルを取得した際、「ブロック内の全データ」をメモリにキャッシュします。
そのため、同じブロック内のグローバルを取得する際は、ディスクアクセスを行わず、グローバル・バッファからデータを取得するため、データ取得処理が高速になります。
先ほどの処理と各ブロックの関係性を確認してみます。
【処理の流れ】
s txt = ^BlockSearch(1) ← No.29842
s txt = ^BlockSearch(2) ← No.29842
s txt = ^BlockSearch(162820) ← No.465390
s txt = ^BlockSearch(163022) ← No.465390
s txt = ^BlockSearch(203) ← No.29842

詳細は「グローバルざっくり解説#1 ブロックって何?」を参照してください。
このブロック構成をイメージしつつ、グローバルキャッシュの動作を確認してみましょう。
各処理とキャッシュの関連性を確認する
先ずは、各処理でディスクへのアクセス数とキャッシュへのアクセス数を、1回目と2回目の実行で比較してみます。
1回目の実行
下記表は、1回目の計測結果をまとめました。
関数「blockCheck()」の処理行(ライン行)毎に、各ブロックへのアクセス回数を記しています。
処理 | 時間 | Disc Dir | Disc Upn | Disc Bpn | Disc Data | Buf Dir | Buf Upn | Buf Bpn | Buf Data |
---|---|---|---|---|---|---|---|---|---|
^BlockSearch(1) | 0.021923 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
^BlockSearch(2) | 0.000006 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(162820) | 0.007185 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 |
^BlockSearch(163022) | 0.000010 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(203) | 0.000006 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Dir=ディレクトリ・ブロック, Upn=上部ポインタ・ブロック, Bpn=下部ポインタ・ブロック, Data=データ・ブロック
※計測のため、各処理は通常の処理よりも遅くなっています。
上記表から、最初のグローバル(^BlockSearch(1))取得は「ディスクアクセスが一番多い」「一番処理が遅い」事が分ります。
表だけではイメージしにくいので、処理の流れを図解してみます。


これらの動作から、「ブロック」単位でメモリにキャッシュしている事が確認できます。
また、ディスクアクセスと比較して、グローバル・バッファへのアクセスがいかに高速に行われるかも分かります。
2回目の実行
では、本題の2回目の処理が早い理由を確認します。
1回目と同様に、各ブロックへのアクセス数をカウントしてみましょう。
処理 | 時間 | Disc Dir | Disc Upn | Disc Bpn | Disc Data | Buf Dir | Buf Upn | Buf Bpn | Buf Data |
---|---|---|---|---|---|---|---|---|---|
^BlockSearch(1) | 0.000009 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(2) | 0.000002 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(162820) | 0.000005 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(163022) | 0.000002 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(203) | 0.000005 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Dir=ディレクトリ・ブロック, Upn=上部ポインタ・ブロック, Bpn=下部ポインタ・ブロック, Data=データ・ブロック
全てのグローバルをグローバル・キャッシュ、しかもデータ・ブロックのみから取得しているので、高速で処理が終わっている事が分ります。
また表より、^BlockSearch(2)は^(1)より処理が早く、^(163022)は^(162820)より処理が早い事が分かります。
これは、同ブロック内のデータを連続で取得している事が理由と考えています。
→ これに関しては、別の記事にて記載します。
他のプロセスではどうか?
グローバル・バッファはプロセス固有ではないので、他のプロセスも同様に処理が早くなるはずです。
検証してみましょう。
処理 | 時間 | Disc Dir | Disc Upn | Disc Bpn | Disc Data | Buf Dir | Buf Upn | Buf Bpn | Buf Data |
---|---|---|---|---|---|---|---|---|---|
^BlockSearch(1) | 0.000090 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
^BlockSearch(2) | 0.000003 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(162820) | 0.000015 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
^BlockSearch(163022) | 0.000004 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
^BlockSearch(203) | 0.000006 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Dir=ディレクトリ・ブロック, Upn=上部ポインタ・ブロック, Bpn=下部ポインタ・ブロック, Data=データ・ブロック
この検証により、下記2点が分かります。
数回別のプロセスで試しましたが、同様の挙動となっています。
また、どのプロセスで検証しても、2回目の実行は全てデータ・ブロックのみを参照しています。
グローバル・バッファの設定方法
様々なグローバルをメモリ上に展開したい場合は、グローバル・バッファを多めに設定した方がいいと思います。
※ 設定は管理ポータル画面の下記で行います。

まとめ
これまでの結果をまとめると下記になります。
以上、グローバルおよびキャッシュの挙動について解説しました。
本記事が、皆さまの実務や学びの中で、少しでもお役に立てれば幸いです。