8

私が現在取り組んでいるプロジェクトには、既存のオブジェクトのディープ コピーを取得するためにシリアル化された多くのオブジェクトがあります。これは、コンポーネント間で 100、200、または 1000 の呼び出しがある場合に、実行時に複数の呼び出しが発生するまでは正常に機能し、これがパフォーマンスの頭痛に見舞われる場所です。

これらのオブジェクトをクローンとしてコピーする歴史的な理由は、異なる機能の下で同じオブジェクトで動作する 2 つの異なるコンポーネントが互いに変更されるべきではないことです。たとえば、Swing UI の変更は、保存または同期ボタンが押されるまでバックエンドのオブジェクト値を変更してはなりません。

私たちにはかなり大きなコード ベースがあります。リフレクションに基づいてクローンを記述すれば、シリアル化に比べて高速に動作すると思いましたが、オブジェクトの複雑な階層またはその他の理由により、このアプローチはさらに遅くなります。

CloneUtils (sourceforge プロジェクト) も使用してみましたが、これも低速です (Hibernate はまったく使用していません)。Spring BeanUtils はオプションではありません (ドキュメントから、Bean のみを使用すると想定しています。

別のコピーで作業しながら、パフォーマンスを向上させます。シリアライゼーションの代わりに独自のコピー メソッドを提供する場合に高速化するオプションがありますが、これには、これらのメソッドを毎回更新するという欠点があり、忘れると機能が失われる可能性があります。

4

4 に答える 4

1

たとえば、 cglibを使用して、動的クラス生成によってリフレクションを回避できます。使用するクラスごとに、コピーに必要なコードを含む「クローン クラス」を生成します。これにより、すべてのフィールドが少なくともパッケージ プライベートであり、コピー クラスを同じパッケージに配置する場合、リフレクションは不要になります。デフォルトのctorが必要で、最終フィールドも必要ありません。

ここでは、シリアライゼーションは を使用してオブジェクトを作成するため、利点がありますsun.misc.Unsafe

各クラスにメソッドを実装するdeepCloneこともオプションです。クローンクラスのアイデアと組み合わせることもできます.

于 2011-02-09T15:35:59.920 に答える
0

このような場合にパフォーマンスを向上させる方法のヒントを教えてください:まだ使用していない場合はプロトタイプパターンを使用してください。ある程度のパフォーマンスが得られる可能性があります。

于 2011-02-09T15:04:48.053 に答える
0

あなたが言及したアプローチに従うことで、パフォーマンスを大幅に改善するためにできることはたくさんあるとは思えません。残念ながら、オブジェクトのコピーには時間がかかります。

少し横に考えて、メモリの量と、読み取りと書き込みの比率 (特に書き込みごとに多数の読み取りがある場合) に応じて、コピーのキャッシュを作成するのはどうですか?

于 2011-02-09T15:06:51.710 に答える
0

あなたが説明するのは、可変状態を管理するための散弾銃のアプローチです。クローンを高速化しようとしても、限られた改善しか得られません (最大で 1 桁まで)。また、ソケット、ストリーム、またはデータベース接続をどのように複製しますか?

本当に必要なのは、コマンドとクエリを適切に分離してアプリをリファクタリングすることです。このようにして、オブジェクトを変更している場所と変更していない場所を知ることができます。不明な場合は、単体テストを使用してこれを確認できます。

役立つテクニックがいくつかあります。オブジェクトの一部を不変に変更できます (そのため、それらを自然に共有し、変更時に新しいコピーを作成できます)。変更可能なオブジェクトに読み取り専用インターフェイスを実装させたり、GUI で RO ビューを使用したりできます。

于 2011-02-09T15:36:42.143 に答える