レポート作成時のメモリ使用量を軽減させる方法について
対象製品
ActiveReports for .NET 7.0J
詳細
ActiveReportsが使用したメモリは、通常、共通言語ランタイム(CLR)のガベージコレクタにより定期的に自動解放されます。この自動解放は、メモリが十分に余っている場合には実行されないため、解放のタイミングやレポートの構造によっては、一時的に使用メモリ量が増加し、OutOfMemoryException等の例外が発生する場合があります。
たとえば、画像を含むレポートは、文字のみのレポートと比較すると、メモリ使用量が大きくなります。毎ページに同じ画像を出力した場合でも、ページ数に比例した量のメモリを使用します。画像の形式にもよりますが、画像をメモリ上に展開したときのサイズ(メモリ使用量)は、画像ファイル自体のサイズよりも大きくなります。
また、ChartコントロールやBarcodeコントロールを使用した場合、グラフやバーコードシンボルは画像として出力されるため、上記と同様である上に、グラフやシンボルを生成するための処理が複雑であるため、これらのコントロールを使用しないレポートに比べてメモリ使用量が大きくなります。
また、レポートをPDFなどの形式にエクスポートする場合には、レポートの生成結果をPDF形式に変換するという処理になるため、Viewerコントロールにレポートをプレビューする場合よりも、消費されるメモリ量は増加します。
ActiveReports を使用したアプリケーションのメモリ使用量を軽減させる方法や、パフォーマンスを向上させる方法としては、以下のような内容が考えられます。
たとえば、画像を含むレポートは、文字のみのレポートと比較すると、メモリ使用量が大きくなります。毎ページに同じ画像を出力した場合でも、ページ数に比例した量のメモリを使用します。画像の形式にもよりますが、画像をメモリ上に展開したときのサイズ(メモリ使用量)は、画像ファイル自体のサイズよりも大きくなります。
また、ChartコントロールやBarcodeコントロールを使用した場合、グラフやバーコードシンボルは画像として出力されるため、上記と同様である上に、グラフやシンボルを生成するための処理が複雑であるため、これらのコントロールを使用しないレポートに比べてメモリ使用量が大きくなります。
また、レポートをPDFなどの形式にエクスポートする場合には、レポートの生成結果をPDF形式に変換するという処理になるため、Viewerコントロールにレポートをプレビューする場合よりも、消費されるメモリ量は増加します。
ActiveReports を使用したアプリケーションのメモリ使用量を軽減させる方法や、パフォーマンスを向上させる方法としては、以下のような内容が考えられます。
- レポートの構造や処理を変更する
- CacheToDiskプロパティを使用する
- コントロール数を減らす
- 画像の形式やサイズをあらかじめ調整する
- サブレポートを使用しない
- データソースの使用方法を変更する
- Sessionに大きなサイズのデータを格納しない
- パフォーマンス オプションを設定する
- パフォーマンスに関する一般的な情報
- 仮想プリンタの設定
- その他の対処
- レポートの構造や処理を変更する
セクションレポートの場合、レポートの構造や実装する処理の内容を変更することで、レポート作成時のメモリ使用量を低減できる場合があります。詳細については、製品ヘルプの以下の内容をご参照ください。
PowerTools ActiveReports for .NET 7.0J
- ActiveReportsユーザーガイド
- 概念
- セクションレポートの概念
- セクションレポートの最適化
- よくある質問
- 共通の項目(ページレポートとセクションレポート)
- 「メモリが大量に消費される場合の対応方法」 - CacheToDiskプロパティを使用する
前述「1.」で案内しているヘルプトピック「セクションレポートの最適化」内の「メモリで考慮すべき事項」の項にあります通り、セクションレポートにはメモリ消費動作を制御するための機能として、CacheToDiskプロパティが用意されています。
CacheToDiskプロパティをTrueに設定することで、レポートの生成処理やPDFエクスポート時に、レポート全体をメモリにロードせずに、一部をディスクにキャッシュするような動作に変わり、その結果、メモリ使用量を低減できる場合があります。
セクションレポートのDocument.CacheToDiskプロパティをTrueに設定し、CacheToDiskLocationプロパティに任意の作業ディレクトリを指定した場合の動作をご確認ください。(CacheToDiskLocationプロパティに設定したディレクトリは、書き込み可能である必要があります。)
ただし、以下のヘルプトピックにあります通り、本プロパティはメモリの使用量が減ることを保証するものではありません。
PowerTools ActiveReports for .NET 7.0J
- クラスライブラリリファレンス
- GrapeCity.ActiveReports.Document.v7 アセンブリ
- 名前空間
- GrapeCity.ActiveReports.Document 名前空間
- クラス
- SectionDocument
- プロパティ
- CacheToDisk プロパティ
CacheToDiskプロパティをTrueに設定した場合、レポート生成中などに消費されるメモリの一部をローカルディスク上の一時ファイルで代用するのみであり、メモリの消費量が一定の値以上にならないよう抑制するわけではありません。
CacheToDiskプロパティをTrueに設定することで、メモリの増加量をある程度抑制できますが、レポート上に出力する画像や生成されるページ数が多くなればなるほど、メモリ消費量は逓増します。
したがって、CacheToDiskプロパティをTrueに設定しても、メモリ不足の事象を完全に回避できるわけではありません。あらかじめご了承ください。 - コントロール数を減らす
レポート上にコントロールが多数配置されている場合、消費するメモリの量も大きくなります。
たとえば、セクションレポートにおいて、Lineコントロールで四角形を構成している場合には、Shapeコントロールで代用する方法や、Shapeコントロールで文字列に枠を出力している場合には、TextBoxやLabelの罫線(コントロール枠線)を使用するといった方法が考えられます。 - 画像の形式やサイズをあらかじめ調整する
レポート上に画像を表示する場合、その画像のサイズや形式もパフォーマンスに影響します。
たとえば、一般的に JPEG形式のように圧縮率の高い画像ファイルは、ファイル自体のサイズは小さくても、メモリ上に展開した場合のサイズは、ピクセルサイズや色数などに依存して大きくなる場合があります。
※ JPEG形式は、画像データを圧縮する形式の一つに過ぎず、実際に画像を表示する際には非圧縮状態に変換しております。これは、ActiveReports の仕様によるものではなく、JPEG形式の一般的な仕様です。
ビットマップの種類
このような場合、JPEG以外の形式に画像ファイルをあらかじめ変換することがパフォーマンス改善に有効な場合があります。お試しください。
また、レポート上に出力する画像のサイズだけではなく、元の画像自体のサイズもパフォーマンスに影響します。
たとえば、PictureコントロールのSizeModeプロパティ(ページレポートの場合、ImageコントロールのSizingプロパティ)の設定によって、コントロールのサイズにあわせて画像を拡大・縮小して表示することが可能です。
しかしながら、これらのコントロール自体のサイズは小さくても、元の画像のサイズが大きければ、その分、メモリを消費します。
SizeModeプロパティ(Sizingプロパティ)を"Clip"に設定した状態(画像の拡大・縮小が行われない状態)で画像が意図した通りに表示されるように、画像自体のサイズをあらかじめ小さくしておくこともパフォーマンス改善に有効な場合があります。前述のファイル形式の変更とあわせてお試しください。 - サブレポートを使用しない
セクションレポートにおいて、サブレポートはそれ自体が一つのレポートとして生成されるため、サブレポートを使用しないレポートと比較すると、メモリ消費量やパフォーマンスの面で劣る場合があります。
レポートの構成にもよりますが、グループヘッダ/フッタセクションを利用することや、レポートにセットするデータソースの構成を変更することで、サブレポートを使用せずに同内容のレポートを実現できる場合もございますので、こちらの方法もご検討ください。
セクションレポートでグループヘッダ/フッタを使用してグループ化を行う方法につきましては、製品ヘルプの以下の内容をご参照ください。
PowerTools ActiveReports for .NET 7.0J
- ActiveReportsユーザーガイド
- サンプルとチュートリアル
- 目的別サンプルとチュートリアル
- 「サブレポートを使用したい」 - データソースの使用方法を変更する
.NETアプリケーション全般の動作仕様になりますが、マイクロソフト社の以下のページにあります通り、DataReaderオブジェクトを使用した場合、DataSetオブジェクトへデータを読み取る場合に比べ、高いパフォーマンスを実現できることが確認されております。
.NET アプリケーションのパフォーマンスとスケーラビリティの向上 - 第 12 章 「ADO.NET パフォーマンスの向上」
非接続型のDataSetではなく、XXXDataReaderなどの接続型オブジェクトを使用するなどの方法で、メモリ使用量を軽減できる場合があります。具体的な方法につきましては、製品ヘルプの以下の内容をご参照ください。
PowerTools ActiveReports for .NET 7.0J
- ActiveReportsユーザーガイド
- サンプルとチュートリアル
- サンプル
- セクションレポートのサンプル(Standard)
- Data
- データバウンド サンプル(DataReaderとのバインド)
- よくある質問
- セクションレポート
- データベース
- 「ODBC データ ソースを使用する」
- 共通の項目(ページレポートとセクションレポート)
- データベース
- 「Oracle データソースを使用する」 - Sessionに大きなサイズのデータを格納しない
ActiveReportsと関係なく、一般的な内容になりますが、大きなサイズのデータをSessionオブジェクトに格納するような処理は、基本的に推奨されていません。
@IT:.NETエンタープライズWebアプリケーション開発技術大全 Sessionオブジェクト
Sessionに大きなサイズのデータを格納している場合には、必要な情報のみをSession経由で受け渡すようにするなどの方法をご検討ください。 - パフォーマンス オプションを設定する
Windowsのパフォーマンスオプションを設定することで、パフォーマンスを向上できる可能性が考えられます。こちらの方法をお試しください。
Windows XP のパフォーマンス オプションを設定する方法
Windows Server 2008 R2 でアプリケーションのパフォーマンスを構成する - パフォーマンスに関する一般的な情報
マイクロソフト社のWebサイトで公開されている以下の情報につきまして、ご確認ください。
.NET アプリケーションのパフォーマンス関連のヒントとトリック
.NET アプリケーションのパフォーマンスとスケーラビリティの向上 - はじめに
ASP.NET のパフォーマンス
ASP.NET Web アプリケーションで System.OutOfMemoryException が発生する場合のトラブルシューティング
[HOWTO] .NET Framework をベースに構築されたアプリケーションのパフォーマンスの調整
パフォーマンスの問題を解決する
アプリケーション開発時のビルド
※上記の内容についてご不明な点がある場合には、お手数ですが、マイクロソフト社にお問い合わせください。 - 仮想プリンタの設定
パフォーマンスとは直接関係ありませんが、Webアプリケーション上でセクションレポートを作成する場合には、仮想プリンタの設定を行った上で、用紙サイズ・方向を設定されることをお勧めいたします。
レポートの作成前に、PrinterクラスのPrinterNameプロパティに""を設定することで、仮想プリンタ機能を使用できます(この際、デザイナ上での用紙サイズは、「プリンタの既定値」に設定してください)。
通常、セクションレポートはレポート作成(実行)時に実行環境上のプリンタ(プリンタドライバ)から、用紙サイズ等の情報を取得します。
仮想プリンタの設定を行った場合、この情報取得を行わず、任意のサイズでレポートを作成します。そのため、情報取得のためのオーバーヘッド発生や、指定した用紙サイズをプリンタがサポートしていない場合に発生する問題を回避することが可能です。
仮想プリンタは、レポートを生成する環境と表示・印刷する環境が異なるWebアプリケーションや、レポートをPDF等の形式にエクスポートする場合に有効となる方法です。
仮想プリンタの詳細や実装方法については、製品ヘルプの以下の内容をご覧ください。
PowerTools ActiveReports for .NET 7.0J
- ActiveReportsユーザーガイド
- 概念
- セクションレポートの概念
- 仮想プリンタ
- よくある質問
- セクションレポート
- 印刷
- 「プリンタドライバがサポートしていない用紙サイズに出力する」 - その他の対処
誠に恐れ入りますが、実装面から提供できる情報は、以上で全てとなります。上記以外に提供できる情報はございません。
たとえば、非常に大量のデータ/画像を元にレポートの生成を行おうとした場合や低スペックの環境でアプリケーションを実行した場合、大量のページが生成されるような場合などは、上記のような対処を行っても問題が解消されないことがございます。
このような場合、ActiveReports 側での対処方法は存在いたしませんので、誠に恐れ入りますが、運用面などからの対処をご検討ください。
たとえば、以下のような対処方法が考えられます。
- 処理を分割し、一度に作成・印刷するレポートのデータ量・ページ数を減らす
- ループ内で繰り返し使用するオブジェクト(PdfExportクラスなど)をループの外で宣言する
- 不変部分は事前に生成してファイルに保存しておく
- 出力データの編集等をイベント内では行わず、予めデータソースの内容を編集しておく
- 実行環境の物理メモリや仮想メモリを増やす
- 実行環境を64bit環境に変更する。(64bitの主な利点については、こちらをご参考ください。)
関連情報
キーワード
HowTo