サイト内検索
サイト内検索を閉じる

オープンシステムで性能を担保するための方策

今回は、前回の予告どおりに「性能を担保するための方策」について説明していきます。

システム開発において発生するトラブルの中には、性能に関するものがあります。性能が出ない原因は様々ですが、起きている性能問題の中には、「CPUリソースには余裕があるが性能がでない」というケースがあります。何等かの理由でCPUリソースを使い切れていないことが原因となっているケースです。では、何故CPUリソースを使い切れていないのでしょうか?それには様々な原因が考えられます。例えばデータベースのロック解放待ちによる場合もありますし、性能が考慮されたAPIを利用していない等も考えられます。いずれにせよ、性能が出ない時は、その原因を細かく分析する必要があります。

コールツリーによる分析

「Xenlon~神龍 Migrator」で変換されたJavaプログラムには、デフォルトの機能として実行時に「コールツリー」を出力する機能が備わっています。この機能は、業務処理を実行した際のプログラム呼び出しをツリー状に出力するものです。我々が開発や保守に関わっていないシステムの移行を行う際に、当該機能がどのようなプログラムによって構成(実現)されているかが判ることで、現行仕様の理解を助けると考え開発を行いました。そして、「新旧比較テスト(注1)」において結果が合わない場合、想定されたテストケースに従った処理が行われているか?を把握することで、結果が合わない理由を推察するのに役立っています。また、このコールツリー出力機能では、CPUコストとElapsed time の両方を測定することもできます。両方を測定する事のメリットとしては、CPUコストは低いにも関わらず、Elapsed time が長い場合には、前述のロック解放待ち等の何らかの待ちや、DB側でコストの高い処理が行われている事が判るからです(ただ、前提として、CPUに余裕がある場合の話です)。CPUコストは、各プログラムが消費する全体コストとインスタンス化コストが分けて出力されますので、問題の切り分けが容易になっています。

性能チューニングにおいては、プロファイラの利用も考えられますが、多過ぎる情報はかえって調査を難しくする場合もありますし、情報量の調整を行うには経験が必要になります。アプリケーションエンジニアにとっては、プログラム単位でコスト把握できた方が、情報量が多過ぎず、わかりやすいと考えています。また開発途上で、自分の測定したい範囲での性能値を、より詳細にコールツリー上に出力させるためのAPIも用意しています。これにより、より細かな原因分析が容易に行えます。加えて、このAPIを利用する際には、追加情報をコールツリーに出力することもできます。例えば、データベースアクセスにおける検索キーの情報を出力することで、更なる問題の明確化が可能となるケースもあります。

では次のセクションでは、「COBOL プログラムをJava 化した際に性能問題が多発する!」と言う迷信を、徐々に取り除いていきたいと思います。

注1 システム移行の際に実施するテスト。移行前の旧システムと移行後の新システムとで動作結果を比較することで正常動作を確認する。

ファイルアクセス

ファイルアクセスがメインのバッチ処理(純バッチ)を、我々のマイグレータを利用して変換し、測定を行うことがあります。その際には、私は自分のローカルPCの環境を利用して、まず動作確認をする訳ですが、その際に、明らかに遅いと感じた事はありませんし、性能観点でのPOC(実環境)においても問題となったことはありません。
私のマシンのスペックは以下の通りです。

CPU:Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
メモリ:16.0 GB
ディスク:m2.SSD

オープン環境でもSSDにより、大量データのバッチ処理がホストコンピュータと比較して何ら遜色ないパフォーマンスが出るようになってきたと思っています。また、たとえ高速なディスクアクセスが可能では無い環境の場合でも、Javaのバッファリング機能をもったファイルAPIを使用し、且つバッファサイズを大きくすることで、性能改善を図ることが可能です。マイグレータにより変換されたコードは、バッファリング機能をもったファイルアクセス・クラスへ処理を委譲します。これにより、前述のようなチューニングが可能となっています。更に変換後のJavaプログラムにおけるファイルへのアクセスは、バイト単位ではなくレコード単位となっていますので、上記のバッファリングの効果も期待できます。
そして、変換後のJavaプログラムにおけるメモリ上のデータ構造は、COBOLと同じく「01」レベル毎に独立したデータ・バッファを持っています。これにより、データコピー(MOVE等)をする際には、JavaのAPI中でも高いパフォーマンスを発揮できるように配慮して以下のAPIを使用しています。

java.lang.System
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
指定位置で開始する指定ソース配列から、転送先配列の指定位置に配列をコピーします。

計算処理

COBOLで開発されたプログラムの移行を考えた際に、「10進数での演算」は避けられない課題です。10進演算を行わないと、COBOLプログラムの実行により得られた値(旧システムの実行結果)と、Javaプログラムの実行により得られた値(新システムの実行結果)が一致しないケースが発生するからです。このような場合、Java開発者は、BigDecimalクラスを利用します。ただし、BigDecimalクラスは、ホスト上での計算処理に比べると性能が劣っていると言われる事があります。確かに計算処理の部分だけを抽出して、速度比較を行った場合、COBOLよりもJavaの方が遅くなる可能性はあります。しかし、実際のアプリケーションではコードの全てが計算処理ではありません。ファイルアクセス、データベースアクセスもあれば、判定処理(IF)、転記処理(MOVE)等もあります。よって評価すべきは、アプリケーションのトータルの性能だと考えています。また、計算処理は、実行するマシンのCPUクロックに大きく影響されます。もし、オープンシステムのCPU性能が、ホストコンピュータのそれと比較して明らかに優れている場合は、マイグレーション後のプログラムの実行速度は、同等もしくはそれ以上になる可能性もあります。加えてJavaには、JITコンパイル(※)という仕組みがあり、これも性能向上に大きく貢献しています。その仕組みの効果を見るために、簡単なアプリケーションを作成してみましょう。予め定められた利息と返済方法に従って毎月の返済額を計算するプログラムを考えてみます。

4,000万円を借入期間30年、全期間固定金利で、毎月の返済額を「元金均等返済」方式で計算します。30年×12ヶ月=360 回の支払いとなり、以下の計算を、360回実行することになります。

元金返済額 = 借入金額 ÷ 返済回数
利息返済額 = 借入金額 × (年利÷12)

CPUコストの計測をするのに、この360回をひとまとめにしてn回実行し、1回あたりのコストの変化を見ます。以下の結果から、CPUコストが、呼び出し回数にしたがって明らかに減少していることがわかります。(最初の計算にかかったコストを、100%としています)

JITコンパイル(Just-In-Time コンパイル)
JVMが実行時に、利用頻度に応じて必要最低限に機械語変換を行うことで、実行モジュールにおける計算量・変換量を必要最低限に抑える。

CPUの進化とメモリの大容量化

さきほど、JITコンパイルに関するJava VM の進化が、大規模な基幹系アプリケーションのマイグレーションの実現(性能問題の解決)に寄与していることを説明しました。加えて、もう一つ大きく寄与しているのが、メモリの大容量化と高速化です。Javaプログラム上でCOBOL言語のメモリ上の振る舞いをエミュレートするためには、どうしても元のCOBOLよりもメモリを多く使用するアーキテクチャを採らざるを得ません。ただ多くと言っても、現在の様な広大なメモリ空間を安価に手に入れられる環境では大きな問題ではありませんが。このようなアーキテクチャを採用する上では、64Bit化は大きな朗報となっています。64Bit化されたことにより提供される膨大なメモリ空間があれば、前述のような「振る舞いをエミュレートする」方式の採用も可能になりますし、必要に応じてデータをキャッシングすることで、CPUパワーをフルに引き出すことが可能になります。

VSAMアクセス

メモリ活用の例として、ホストコンピュータのCOBOLで提供されているVSAMファイルについて解説します。VSAM(仮想記憶アクセス方式)は、ホストコンピュータ特有の機能であり、ファイルに対してレコード単位でデータを格納し、順序アクセスおよびキーアクセスが可能です。よって、オープン環境で実現するには、ファイルではなくRDB化して、SQLにより順序アクセスおようびキーアクセスを実現します。
VSAM へのアクセス命令において、START と言う命令があります(使用方法は以下の通り)。

START 【VSAMファイル】 KEY >= 【VALUE】

これにより、VSAMファイルに対する「読み出しの開始位置」を指定する事ができます。
指定後は、以下のNEXT 命令により、レコードをKEY順に従って順次読み出していくことができます。

READ 【VSAMファイル】 NEXT

このような命令を、RDBの基本的な機能だけで実現しようとすると、性能劣化を招いてしまう可能性があります。理由は、START 命令の度にSELECT 命令を発行し、その際にはORDER BYによるソート処理を実行する必要があるからです。ソートが必要な理由は、この命令の後続で実行されるREAD~NEXT命令においてKEY順に読み進める必要があるからです。このようなSTART命令によるアクセスが、バッチ処理の最初に1度だけ行われ、その後はREAD ~ NEXTしか呼び出さないのであれば問題は無いですが、この辺りはプログラムの作りに依存してしまいます。
このような機能の実現には、対象のVSAMファイルのオープン時に、キーおよびデータの両方(またはキーのみ)を昇順指定して予めメモリに読み込みキャッシュ化する方法を採ります。その後、START命令おいて指定された値を条件とした読み出し開始位置の探索を行います。探索は、2分探索と同等のロジックにより行い、探索結果の位置を「カレントポジション」として管理します。探索の際には、【VALUE】に指定された値がKEYのリストから必ず見つかる訳では無いことを考慮し、2分探索のロジックを少しカスタマイズする必要があります。次に、NEXT 命令が発行された場合、カレントポジションのデータを取得した後に、条件が「>=, >」の場合はポジションUPし、「<=, <」の場合はDOWNすれば良いことになります。キャッシュ化されるデータのサイズ(レコードサイズ×レコード数)を考慮し、キャッシュの対象をキーのみとした場合は、データの取得は都度データベースから読み取ることになります。
(※トランザクションとの関連性については、ここでは割愛しています)

呼び出し最適化(特許取得技術)

「Xenlon~神龍」には、マイグレーションで発生し易い性能問題に予め対処するための技術を開発し、特許を取得しています。例を挙げますと、前回すこし触れました引数データを、参照渡しにするための変換手法がそれに当たります。我々はこの手法を「呼び出し最適化」と呼んでいます。まず、変換において発生する【課題】について説明します。
以下のようなプログラムにおいて、特別な考慮を行わずにJava変換した場合、呼出し元「到着時刻」と呼出し先「検証時刻」とでは項目名が異なるため、変換後のJavaではクラス名が異なるため型の不一致が生じます。これにより代入が行えず、末端項目(時、分、秒)を、 コピーして受け渡す 必要があり、性能劣化を引き起こしてしまう可能性があります。本例では項目数が少ないため大きな問題にはなりませんが、項目数が多いと問題を引き起こしてしまいます。

この問題を解決するために、Xenlon~神龍 Migratorは、以下のアプローチを採用しています。
Step01【分析ツールによる呼出し先の引数解析】
以下の情報を抽出し、結果を蓄積していきます。
[プログラム名、引数のCOPY句名/COPY句内の最上位の集団項目名(引数の個数分)]

Step02【変換ツールによる呼び出しシグニチュアの最適化】
分析結果に基づいて、引数の受け渡しを オブジェクトの参照渡し にすることで、項目数分のコピー等を行わないようにすることが可能となり高速化できます。

このように、「変換ツールが、変数参照において、自動で項目を補う」ことで課題の解消を図っています。

業務処理以外の性能について

また、Javaが遅いとよく言われる理由のひとつとして、Java VM の起動コストや、データベースコネクションの取得コストが挙げられることがあります。ひとつのバッチアプリケーションが処理するデータ量が多い場合は、バッチ処理全体の処理時間も比例して長くなるため、上記の初期コストは微々たるものとして無視することができます。しかし、処理対象件数の少ないバッチ処理を沢山実行するような場合は、上記の初期コスト(準備コスト)を無視することができないケースがあります。そのような場合は、バッチ処理実行用のサーバを起動させておき(加えて、データベースコネクションもプーリングしておき)、そのサーバに当該バッチアプリケーションの起動命令を発行することで、上記のコストを削減するのも一つの手段です。その実現方法として、jBatchやSpring BatchなどのJavaプロセスを常時起動させておくフレームワークを利用するのも1案です。ただし、システムをオープン化した後で、個々のアプリケーションを細かく見ていくと、速くなる部分もあれば遅くなる部分もあると思います。重要なのは冒頭でも申し上げました通り、トータルのバッチ処理時間が、オープン化後どうなったか?が重要であり、その観点で評価するのが適切だと考えています。

最後に

性能問題は、技術の進化によって自動的に解決されていくものもありますが、現時点での進化の度合いでは解決できないものもあります。解決できないものに対しては、何等かの対策(新たな変換ロジックの開発や、エミュレート・ライブラリのチューニング)を講じることで、解決できるはずだと考えています。解決に至るためには、起きている問題を正しく認識し、問題の本質を見極めることが出発点であると思いますし、欲張らずにひとつずつクリアしていくことが大切だと思っています。

「Xenlon~神龍 モダナイゼーションサービス」製品ラインナップ

Xenlon~神龍 モダナイゼーションサービス」シリーズはTIS独自のリライト手法によるマイグレーションを中心としたモダナイゼーションサービスで企業のDX推進をご支援します。

アセスメントサービス リライトによるモダナイゼーションを検討中の企業様に対して「Xenlon~神龍 モダナイゼーションサービス」を活用したプロジェクト推進の『実現性』と『実効性』を検討します。
さらに、ご希望のお客様に対しては情報システム化戦略やエンハンス革新戦略・DX戦略の評価・診断をご支援します。
マイグレーションサービス TIS独自のリライト技術「Xenlon~神龍 Migrator」を活用して、レガシーな言語(COBOL、PL/Ⅰなど)からJavaへのリライトを実現し、オープン環境へ移行します。業務ロジックの100%を自動変換するとともに、メインフレームと同等以上の処理性能を実現します。
エンハンス革新・DX推進サービス マイグレーション後の早期エンハンス革新やDXの実現に向け、各種戦略やマイグレーションプロジェクトからの情報をインプットにしてエンハンス革新計画・DX計画を立案。
PoCを実現しながら実現性を検証するとともに、必要に応じて、マイグレーションプロジェクトにフィードバックすることで早期にエンハンス革新・DX実現に向け推進します。
エンハンス革新・DX実践サービス システムの正常稼働を保つためのメンテナンスをはじめ、オープンシステムの手法を有効活用した安全なリファクタリングやエンハンスメント革新の実践によるシステム効率を支援します。またマイグレーション後のシステムをベースとして、データ利活用や先端技術活用などDX実践を支援します。

PAGE TOP

サービスに関する資料をご希望の方は、フォームに必要事項を入力いただき、ご送信ください。

資料を請求する

お問い合わせ
各種お問い合わせページ
お問い合わせフォーム
サービスに関するお問い合わせ
お電話
0800-600-9810
携帯電話
050-5816-9805
受付時間 9:00~12:00 13:00~17:00(土・日・祝日を除く)

更新日時:2023年1月6日 13時42分