こんにちは、開発部の土岐(福岡県北九州市小倉出身)です。と出身を小倉まで書いたのは理由がありまして、福岡出身っていうと「あーあの中洲の」「博多の」みたいな話になるんですが、中洲や博多がある福岡市と小倉のある北九州市の文化圏ってかなり違っていて、私はほとんど福岡市の方に行ったことないんですよね。なので、ビミョーにその話に乗れなかったりして話がいまいち弾まなかったり・・・とかよくあります。大阪と京都みたいな距離感のイメージかな・・・。ということで、福岡市と北九州市は違うもの、ということを覚えていただければと思います。ちなみに私は故郷に思い入れは特にありません。
いきなり話がずれましたが本題に入ります!
先日4月17日に開催されたdstn技術者交流会『dstnHUB』において、「DataSpiderインターナル ~DataSpiderはなぜ高速なのか~」のPart1「アーキテクチャ編」ということで。DataSpiderの高速化技術について発表を行いました。
(dstnHUBの模様についてはブログ記事「 4月17日(木) dstnHUB開催報告!!」を参照ください)
というわけで、早速ですが当日のプレゼンで使用した資料がこちら。
今回のプレゼンは以下のような3つの軸で説明を行いました。
1) スクリプトのコンパイラ型実行
2) PSP&スマートコンパイラによる大容量処理高速化
3) 各コンポーネントのパフォーマンス最適化実装
今回のブログでは「2) PSP&スマートコンパイラによる大容量処理高速化」の説明を補足しながら、今回のイベントのために作られた「PSP Monitor」機能を使ってPSPの実力を検証したいと思います。
(なお、「1) スクリプトのコンパイラ型実行」と「3) 各コンポーネントのパフォーマンス最適化実装」についても、DataSpiderおよびJava技術者にとってなかなか興味深い内容であると思います。ぜひ資料を参照ください!)
PSPフローって結局どう動くの?
というわけでここまででも10回くらい言及してきたPSP。某ゲーム機のことではありません。「Parallel Stream Processing」の略語のDataSpider用語で、スクリプトの実行パフォーマンス高速化&メモリ使用量低減のための機構であります。本サイトでも、以下のようにDataSpider Servista 3.1の新機能「スマートコンパイラ」の紹介の中で取り上げましたので、ご存じの方も多いかと思います。
・ dstnインタビュー 「開発者が語る #1」 DataSpider Servista 3.1新機能"スマートコンパイラ"について小野和俊に聞く
・ DataSpiderデザインパターンβ 第5回 スクリプトパターン 「Smart Compiler」
スマートコンパイラについて詳しくは上記の記事を参照していただくとして、このPSP。「なんか凄そうだけど結局なんなのか分かりにくい」という噂を耳にします。特にPSPについての説明に必ず出てくるこのイメージ図。
▲PSPの処理イメージとしてヘルプなどで使用されている図、だが・・・
アーキテクチャ的には正確な絵ではあるんですが、「で、結局どういう動きになるの?」 というのがいまいち伝わらないのでは・・・と危惧を感じていた私であります。そこで! 今回のプレゼンでは「結局どういう動きになるのか」というところに焦点をあてて、説明を行いました。で少しその説明を振り返ってみます。
まず資料からこちらの通常フローの処理イメージの図。
▲通常フローの処理イメージ
これはPSPフローではない通常のスクリプトの実行の経過を簡単な図にしたものです。スクリプトは通常実行されると、プロセスフローによって接続された処理が次々と実行されます。つまり上記の図で言うと「読み取り」「変換」「書き込み」の各処理が終わってから次の処理へ・・・というように順次実行されていくこととなります。そのため、その総実行時間は各処理の実行時間(+α)となります。また、次の処理に渡すための中間データの容量(通常はメモリに保持されます)は、その処理の出力データがすべて保持されます。
ではこれがPSPフローだとどうなるか? というのがこちらの図。
▲PSPフローの処理イメージ
通常フローと違って、「読み取り」「変換」「書き込み」の各処理は、前の処理の終了を待ちません。一定単位(1000件)の処理が終わったら、次の処理にそのデータを受け渡し、並行して処理を行っていきます。このため、総実行処理はすべての処理の合計時間よりも短くなることが容易に想像できるかと思います。また中間データの容量も一定単位に抑えられるため、データ数が多い場合でもメモリを逼迫することなく処理を行うことができます。
素晴らしいですね!
という資料を今回のイベントに向けて作りながら、開発がメインの業務であるところの私。単に「こうなりますよ」という話だけではなく、「本当にそういう処理になってる!」ということを一目で分かるようなデモを作れないかなーと思いました。ということで開発したのが「PSP Monitor」であります。
PSP Monitorで検証!
PSP Monitor機能は、PSP Monitorアダプタと、データの処理状況を表示するブラウザに表示されたHTMLから構成されています。以下の画面説明図をご覧ください。
▲PSP Monitorの画面説明
上記画面では、左にDataSpider Studioのデザイナが表示され、PSP Monitorアダプタが配置されたスクリプトを実行されています。右側はブラウザで、読み取り・変換・書き込みの各処理の処理件数がオレンジのバーで、「読み取り~変換」と「変換~書き込み」の間の中間データ容量が緑のバーで表示されています。このバーがリアルタイムで更新されていくことで、スクリプトのデータ処理実行の様子がグラフィカルに分かる、というわけです。
PSP Monitorアダプタの各処理では、データ1件辺りの処理ミリ秒を設定できるようになっています。これによって、さまざまな条件でどのようなデータ処理が行われているか、ということが検証できる、というわけです(なお、このアダプタでは特に何かの処理を行っているわけではなく、ダミーのデータを渡しているデモ用のアダプタです)
では早速動かしてみましょう! といっても画像だと分かりにくいので、スクリーンをキャプチャしてYoutubeに動画をアップしてみました!
まずは通常フローで5000件のデータを処理した場合です。3つの処理はすべて1件あたり1ミリ秒時間がかかるように設定しています。
▲通常フロー実行時。前の処理が終わってから次の処理が行われる
GET(読み取り処理) → CONVERT(変換処理) → PUT(書き込み処理)で、5000件処理した後(オレンジのバーが右に行き着いた)後、次の処理が始まっていることが分かると思います。また、中間データ(緑色のバー)は処理したデータをすべて溜めた後、次の処理にデータが渡されて処理されていっていますね。これが通常処理の順次処理です。だいたい28秒程度かかっています。
さあ、いよいよPSPフローで実行してみましょう。DataSpider Servista 3.1で実装された「スマートコンパイラ」の機能で、この処理を簡単にPSPフローにすることができます。プロジェクトエクスプローラでスクリプトを選んで右クリックして、「PSPデータフローの操作」→「一括で有効にする」をクリックしてPSPデータフローを有効にして・・・・実行!
▲上のスクリプトをPSPフローで実行している様子。各処理が並行してデータを処理している様子が分かる
今度は前の処理の終了を待つことなく(オレンジのバーが右に行く着くことなく)、次の処理が実行されているのが分かると思います。各処理は一定数(1000件)のデータごとに次の処理にデータを渡し、並行して処理を行っています。このため総実行時間はおよそ11秒。3倍近く速くなっていますね。
速い!
というわけで、通常フローとPSPフローのデータ処理の違いについて、上のデモで体感していただけたかと思います。
さらに検証! PSPフローでのメモリ使用量低減の効果の程は?
通常フローとPSPフローの違いについては分かったとして、今度はPSPフローで各処理の処理時間が異なる場合、どのような動きになるかやってみましょう。
まず読み取り処理に時間がかかる場合について実験してみましょう。以前の動画はすべての処理に1件あたり1ミリ秒かかる設定でやっていましたが、今回は読み取り処理だけ1件ごとに3ミリ秒かかる設定にしています。
▲読み取り処理が遅い場合のPSPフローの実行の様子。変換・書き込み処理はデータが受け渡されるのを待ちながら実行されている
先ほどとは動きが変わってきましたね。変換・書き込み処理は処理が受け渡されたデータの処理が終わったら、次のデータが受け渡されるのを待って実行されているのが分かります。このように、PSPフローでは「処理できるデータがあれば処理をする、無い場合は待つ」というように少しでも並列に処理できるものは行えるようにして、パフォーマンスを向上させていることが分かります。
では書き込みが遅い場合はどのような動きになるのでしょうか? というのが下の動画。特に、GET(読み取り)・CONVERT(変換)のバーの動きにご注目ください。(なお、動きを分かりやすくするためにこの動画だけ10000件のデータを処理しています)
▲書き込み処理が遅い場合のPSPフローの実行の様子。読み取り・変換処理は、必要以上の中間データを溜め込まないように待機しながら処理を行っている
この動きは意外に思われた方も居るかもしれません。処理に時間がかかるのは最後の書き込み処理ですが、読み取り・変換処理もその処理経過を待ちながら一定件数ごとに処理が実行されています。これがPSPフローが「低メモリ負荷」の処理であることの理由である動きです。
想像してみてください。もしこのような処理待ちを行わないとすると、読み取り・変換処理は先にすべての処理を終えてしまい、中間データ(緑色のバー)の大きさは処理するデータ件数に従って大きくなることになります。つまり使用可能なメモリが無い場合に起こるエラーOutOfMemoryErrorが起こる可能性があります。
上の動画の動きのように、書き込み処理が遅いため変換~書き込みの間の中間データの容量は多くなっていきますが、一定件数に達すると変換処理は待機してそれ以上大きくならないように待ちます。それに伴い読み取り処理も待機しています。そしてある程度中間データが少なくなると(書き込みが進むと)、再び再開して処理を行っています。これによって、必要以上の中間データを溜めこみ過ぎることなく、また処理パフォーマンス落とすことなく、PSPフローの処理が行われているのです。まるで人間のように次の処理に気を使いながら処理してるようですね。
賢い!
ということで、この動きでPSPフローのが一定容量のみのメモリ使用量を保つ「低メモリ負荷」の処理となっていることが確認できたかと思います。
終わりに
以上が今回のPSP Monitorの内容となります。いかがだったでしょうか? このような「高速」「低メモリ負荷」の処理が可能なPSP機能は3.1のスマートコンパイラによってさらに使いやすくなりました。ぜひご活用ください。
注意点としては、今回の検証でも分かるように、PSPフローは「全体のデータの一部分のデータのみ」を次の処理に渡すことで実現しています。そのため、テーブル型のデータでは使用可能ですが、一部分のみデータが渡すことが不可能なXML型には適用できません。またテーブルデータの処理でも、アダプタ・Mapperのロジックによっては「一部分のデータのみ」という処理が不可能な場合があり、その際には適用できません。詳細についてはヘルプ等をご参照ください。
さて、今回の処理を行ったPSP Monitorアダプタ、またPSP Monitorの画面がどのような内部処理になっているか気になる方もいらっしゃるのではないでしょか。実際にはこれらのアダプタに加えて、HTTPトリガーを利用してこのPSP Monitorの全体の機能が成り立っています。その内部処理については、近日中に記事で紹介したいと思います。またその際には、実際にお手持ちのDataSpiderでも実行できるようにモジュールとインポート用データも公開する予定です。楽しみにしてお待ちいただけると幸いです。
それではご清聴ありがとうございました!