Java Platform, Standard Editionトラブルシューティング・ガイド
目次      

12.1 一般的なパフォーマンス問題

このトピックでは、Java 2Dハードウェア高速化レンダリング・プリミティブに関する一般的な問題、プリミティブ・トレースを検出して非高速化レンダリングを回避する方法について説明します。レンダリング・パフォーマンスの低下には様々な原因が考えられます。次のトピックでは、アプリケーションのレンダリング・パフォーマンスの低下の原因を特定し、ソフトウェアのみのレンダリング・パフォーマンスを改善するためのアプローチを提案します。

このトピックでは、次の項目について説明します。

12.1.1 ハードウェア高速化レンダリング・プリミティブ

パフォーマンス問題の原因についての理解を深めるため、ハードウェア高速化の意味について考えてます。

一般に、ハードウェア高速化レンダリングは2つのカテゴリに分けられます。

  • 「高速化対象」の宛先へのハードウェア高速化レンダリング。ハードウェア高速化が可能なレンダリングの宛先の例として、VolatileImage、画面、およびBufferStrategyがあげられます。ある宛先が高速化対象である場合、そのような表面に対するレンダリングはビデオ・ハードウェアによって実行される可能性があります。したがって、ユーザーがdrawRect呼出しを発行すると、Java 2Dはその呼出しを、ベースとなるネイティブAPI (GDI、DirectDraw、Direct3D、OpenGL、X11など)にリダイレクトし、そこでハードウェアを使って操作が実行されます。

  • 高速化メモリー(ビデオ・メモリーまたはピックスマップ)へのイメージのキャッシング。これにより、それらのイメージを別の高速化対象表面に非常に高速でコピーできるようになります。そのようなイメージは「管理対象イメージ」と呼ばれます。

理想的には、高速化対象表面に対して実行される操作はすべて、ハードウェアで高速化されます。この場合、アプリケーションはプラットフォームによって提供されるメリットを最大限に享受できます。

残念ながら多くの場合、デフォルト・パイプラインはレンダリングにハードウェアを使用できません。その原因は、パイプラインの制限やベースとなるネイティブAPIにあります。たとえば、ほとんどのXサーバーは、アンチエイリアス・プリミティブのレンダリングやアルファ合成をサポートしません。

パフォーマンス問題の原因の1つは、実行される操作がハードウェア高速化されない場合にあります。宛先表面が高速化される場合でも、その一部のプリミティブが高速化されない可能性があります。

ハードウェア高速化が使用されていない場合を検出する方法を知ることが重要です。それを知れば、パフォーマンスの改善が容易になる可能性があります。

12.1.2 非高速化レンダリングの検出および回避のためのプリミティブ・トレース

高速化されないレンダリングを検出するには、Java 2Dプリミティブ・トレースを使用できます。

Java 2Dには組込みのプリミティブ・トレースが含まれています。「Java 2Dテクノロジのシステム・プロパティ」のtraceプロパティの説明を参照してください。

アプリケーションの実行時に-Dsun.java2d.trace=countを指定します。アプリケーションが終了すると、プリミティブのリストとそれらのカウントがコンソールに出力されます。

MaskBlitプリミティブや任意のGeneral*プリミティブが表示された場合、それは通常、レンダリングの一部がソフトウェア・ループによって処理されていることを意味します。Linux上で、半透明のBufferedImageに対してdrawImageを実行してVolatileImageに書き込む場合の出力を、次に示します。

sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, "Integer BGR Pixmap")sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntBgr)

デフォルト・パイプラインでの一般的な非高速化プリミティブと、トレース出力に示されるそれらの特徴をいくつかあげてみます。注意: このトレースのほとんどはLinuxで行われたものです。使用しているプラットフォームや構成によっては多少の違いが生じる可能性があります。

  • 半透明イメージ(ColorModel.getTranslucency()Translucency.TRANSLUCENTが返されるイメージ)、またはAlphaCompositingを使用したもの。サンプルのプリミティブ・トレース出力:

    sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb,SrcOverNoEa, "Integer BGR Pixmap")sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntBgr)
    
  • アンチエイリアスの使用(アンチエイリアス・ヒントの設定による)。サンプルのプリミティブ・トレース出力:

    sun.java2d.loops.MaskFill::MaskFill(AnyColor, Src, IntBgr)
    
  • アンチエイリアス・テキストのレンダリング(テキスト・アンチエイリアス・ヒントの設定)。サンプル出力は次のいずれかになります。

    • sun.java2d.loops.DrawGlyphListAA::DrawGlyphListAA(OpaqueColor, SrcNoEa, AnyInt)
      
    • sun.java2d.loops.DrawGlyphListLCD::DrawGlyphListLCD(AnyColor, SrcNoEa, IntBgr)
      
  • アルファ合成(半透明カラー(0xff以外のアルファ値を含むカラー)でのレンダリング、Graphics2D.setComposite()によるデフォルト以外のAlphaCompositingモードの設定、のいずれかによる)。

    sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOver, IntRgb)sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntRgb)
    
  • 本格的な変換(単なる移動ではない変換)。変換された不透明イメージのVolatileImageへのレンダリング。

    sun.java2d.loops.TransformHelper::TransformHelper(IntBgr, SrcNoEa, IntArgbPre)
    
  • 回転されるラインのレンダリング。

    sun.java2d.loops.DrawPath::DrawPath(AnyColor, SrcNoEa, AnyInt)
    

アプリケーションをトレース付きで実行し、不要な非高速化プリミティブを使用していないことを確認してください。

12.1.3 低いレンダリング・パフォーマンスの原因

いくつかのレンダリング・パフォーマンスの低下の原因および可能な選択肢を次に示します。

12.1.4 ソフトウェアのみのレンダリングのパフォーマンスの改善

アプリケーションが(BufferedImageへのレンダリングのみを行うかデフォルト・パイプラインを非高速化パイプラインに変更したために)ソフトウェア専用レンダリングに依存している場合、あるいはアプリケーションが混在されたレンダリングを行う場合でも、次に示す特定のアプローチによってパフォーマンスが改善します。

  1. 最適化されたサポートとイメージの種類または操作:

    プラットフォーム全体のサイズ制約のために、あるイメージ形式を別の形式に変換するための最適化されたルーチンは、Java 2Dには限られた数しか含まれていません。最適化された直接ループが見つからない状況では、Java 2Dは中間イメージ形式(IntArgb)を介して変換します。この場合、パフォーマンスが低下します。

    Java 2Dプリミティブ・トレースを使用すればそのような状況を検出できます。

    drawImage呼出しに対して2つのプリミティブが存在します。1つ目はイメージをソース形式から中間IntArgb形式に変換し、2つ目は中間IntArgbから変換先の形式に変換します。

    そのような状況を回避する2つの方法を次に示します。

    • 可能であれば別のイメージ形式を使用します。

    • イメージを、よりサポート・レベルの高い形式(INT_RGBINT_ARGBなど)の中間イメージに変換します。そうすれば、カスタム・イメージ形式からの変換が、コピーごとに発生する代わりに一度だけ発生するようになります。

  2. 透明と半透明:

    できれば、完全な半透明(INT_ARGBなど)のイメージではなく、1ビット透明(BITMASK)のイメージをスプライトとして使用することを検討してください。

    完全なアルファを持つイメージの処理では、CPUの負荷がより高くなります。

    1ビット透明イメージを取得するには、GraphicsConfiguration.createCompatibleImage(w,h, Transparency.BITMASK)の呼出しを使用します。

目次      

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.