3

現在、マップレンダリングライブラリのパフォーマンスを改善しようとしています。時間指定記号の場合、ライブラリは実際には、各場所に同じ画像を何度も描画することがよくあります。ただし、シンボルのパラメータ化は非常に豊富であるため、描画プロセスは非常に複雑になる可能性があります。ポイントごとに、描画しようとしている画像を計算するツリー構造があります。前に述べたように、パラメーターが処理中のデータに依存しない場合は、複雑なシンボルを数回描画するだけです。

キャッシュメカニズムを実装しようとしました。すでに描画されている画像を保存し、すでに満たされている構成に遭遇した場合は、画像を取得して再度描画します。私が行った最初のテストは、非常に単純なシンボルに対するものです。形もインテリアも塗りつぶされた円です。

シンボルはすべての場所で一定になることがわかっているので、シンボルをキャッシュして、キャッシュされた画像から再度描画します。それはうまくいきます...しかし私は2つの重要な問題に直面しています:

  • 描かれたシンボルの品質はほとんど損なわれません。
  • さらに問題があります。マップのレンダリングに必要な時間は、キャッシュを使用しない場合よりもキャッシュを使用した場合の方が実際に長くなります。それはキャッシュにとってかなり残念です^_^

キャッシュメカニズムがオンの場合のコアコードは次のとおりです。

if(pc.isCached(map)){
    BufferedImage bi = pc.getCachedValue(map);
    drawCachedImageOnGeometry(g2, sds, fid, selected, mt, the_geom, bi);
} else {
    BufferedImage bi = g2.getDeviceConfiguration().createCompatibleImage(200, 200);
    Graphics2D tg2 = bi.createGraphics();
    graphic.draw(tg2, map, selected, mt, AffineTransform.getTranslateInstance(100, 100));
    drawCachedImageOnGeometry(g2, sds, fid, selected, mt, the_geom, bi);
    pc.cacheSymbol(map, bi);
}

drawCachedImageOnGeometryで行われる唯一の興味深い呼び出しは

g2.drawRenderedImage(bi, AffineTransform.getTranslateInstance(x-100,y-100));

BufferedImageではなくVolatileImageインスタンスを使用しようと試みましたが、それはより深刻な問題を引き起こします(必要になるたびに画像が正しくレンダリングされるかどうかを確認できませんでした)。

私もいくつかのプロファイリングを行いましたが、キャッシュを使用する場合、最も時間がかかる操作はawtで行われたレンダリング操作であるようです。

そうは言っても、私の戦略は間違っていると思います...したがって、私の質問は次のとおりです。

  • 私が説明した目標を達成するための効率的な方法はありますか?
  • もっと正確に言えば、シンボルを描画するために使用されるAWT命令を保存し、必要に応じてそれらを変換する方が速いでしょうか?シンボルの作成に使用された「コマンド」を取得できる可能性があると思います...ワールドワイドウェブではそれに関する情報はあまり見つかりませんでしたが...可能であれば、それは節約になりますシンボルの計算時間(前述のように非常に複雑になる可能性があります)とシンボルの品質の両方を私に伝えます。

あなたが私に与えるすべての情報とリソースを事前に感謝します:-)

エイジメン。

編集:レンダリングできるグラフィックスの詳細は次のとおりです。私が実装しているシンボルモデルによると、グラフィックは非常に単純(つまり、その形状で塗りつぶされた正方形)だけでなく、非常に複雑(たとえば、形状と塗りつぶしの両方がハッチで描かれているラベル、およびハローの場合でも)になります。私が望むならそれの周り)。ほとんどの構成で次のことができると確信しているため、キャッシュを使用したいと思います。

  • 同じスタイルでスタイル設定された同じソースの2つの異なるシンボルを描画するために使用されたパラメータを区別します。
  • 同じパラメータ(場所を除く)を持つ2つのソースが、同じスタイルに対して同じシンボルを生成することを確認してください。ただし、2つの異なる場所にあります(翻訳のみが必要です)。

これらの2つのポイントがあるため、キャッシングは良い戦略のようです。さらに、同じ画像に何千もの重複したシンボルが描画される場合があります。

4

1 に答える 1

2

あなたの絵が実際にどのような種類の操作を必要とするかについて、あなたは非常に漠然としているので、私があなたに与えることができるのは、非常に一般的な指針です.

1.) 事前にレンダリングされたイメージの描画は、Graphics2D 操作を使用して同じイメージを描画するよりも必ずしも高速ではありません。画像の描画に必要な複雑さに大きく依存します。極端な例として、fillRect() と、事前にレンダリングされた四角形を含む Image の drawImage() を考えてみます (fillRect は宛先ピクセルを書き込むだけで、drawImage もソースからコピーする必要があります)。

2.) ほとんどの場合、VolatileImage を直接いじりたくないでしょう。BufferedImage は、Image DataBuffer をいじらない限り、VolatileImage を自動的に利用します。事前にレンダリングされたイメージが多数ある場合、高速化されたビデオ メモリが不足し、イメージ描画のパフォーマンスが低下する可能性があります。

3.) 事前にレンダリングされた画像のオンザフライのスケーリング/回転などは、かなりコストがかかる可能性があります (プラットフォームと現在のグラフィックス変換によって異なります)。

4.) 作成した「互換性のあるイメージ」は、実際には描画ターゲットと互換性がない場合があります。デフォルトの画面デバイスと互換性のある画像を取得しますが、これはマルチ モニター セットアップの実際のターゲットと互換性がない場合があります。実際のターゲット コンポーネントの createImage() を使用すると、より良い結果が得られる場合があります。

編集:

5.) レンダリング操作の座標を変換すると、生成される宛先ピクセルが変更される場合があります。明らかなケースは、座標が非整数の場合です (座標自体、またはグラフィックスに設定された AffineTransform を介して間接的に)。また、テキストやその他のプリミティブのアンチエイリアシングは、座標によってわずかに影響を受ける可能性があります (サブピクセル レンダリングが思い浮かびます)。


シンボルのレンダリングがおそらく速いか遅いかを区別するアプローチを試みることができます。速いものは直接レンダリングされ、遅いものはキャッシュされます。ここでの主な問題は、どちらが速いか遅いかを判断することです。これを判断するのは簡単ではないと思います。

また、グラフのごく一部しかウィンドウ/フレームに収まらないため、それらのほとんどを切り取る必要があると思うので、レンダリングするシンボルが何千もあると言うのはいつですか? その場合は、キャッシュをあまり気にしないでください。現在のクリップ境界から完全に外れた描画操作は、比較的安価です。グラフィックス ターゲットが実際に行うのは、それらが完全に見えないかどうかを検出することだけであり、何もしないときだけです。目標が、ディスクに保存する/印刷する (何でも) 画像を生成することである場合、これは比較的まれな操作であり、実際の印刷はレンダリングに必要な時間をはるかに超える可能性があるため、レンダリングの高速化についてあまり気にしません。とにかくグラフ。

上記のいずれにも当てはまらない場合は、キャッシュされたバージョンが存在するかどうかを判断するために、キャッシュが実際にレンダリング時間を節約するよりも多くの時間/メモリを使用しないように注意してください。また、ターゲットに直接レンダリングする代わりにキャッシュされたイメージを作成すると、そのイメージが再利用されない場合、時間がかかることも考慮する必要があります。キャッシュは、画像が少なくとも 1 回、できれば何度も再利用された場合にのみ、速度を上げることができます。

プリミティブ レンダリング操作オブジェクト (Rectangle、Halo、および Text レンダリング オブジェクトのサブクラスがあるように) を組み合わせてプリミティブ操作からシンボルを構築する場合、それらのそれぞれにコスト インジケーターを割り当て、一部を超えるシンボルのみをキャッシュすることができます (コストのしきい値。また、プリミティブ操作ごとに hashCode() を実装し、シンボル自体を fast(er) equals 検出用に実装することをお勧めします。

于 2012-07-13T15:11:04.677 に答える