私は最近、単純な2Dゲームの作成を開始し、ジレンマに遭遇しました。オブジェクトのx位置とy位置にgetterメソッドとsetterメソッドを使用するかどうかです。メソッドを使用しない方が明確に見えますが、代わりに変数に直接アクセスします。また、オブジェクトに対する多くのメソッド呼び出しはパフォーマンスを低下させます。また、位置の取得と設定はほとんど単純なままなので、ここでカプセル化する必要は本当にありませんか?それとも、常にゲッターメソッドとセッターメソッドの規則に固執する必要がありますか?
4 に答える
慣習に固執することは常に良いことです。さらに、JITは、すべてのメソッドスタックを経由するのではなく、フィールドに直接アクセスするために操作を簡素化します。
これは、メソッドのインライン化と呼ばれます。
JavaVMのJava2リリースは、実行時に単純なメソッドを自動的にインライン化します。最適化されていないJavaVMでは、新しいメソッドが呼び出されるたびに、新しいスタックフレームが作成されます。新しいスタックフレームの作成には、追加のリソースとスタックの再マッピングが必要です。その結果、新しいスタックフレームを作成すると、わずかなオーバーヘッドが発生します。
メソッドのインライン化は、プログラムが行うメソッド呼び出しの数を減らすことでパフォーマンスを向上させます。Java VMインライン化コードは、定数を返すか、内部フィールドにのみアクセスするメソッドをインライン化します。
資力 :
同じトピックについて:
getterとsetterを使用したり、属性を公開したりしないでください。
代わりに、.updatePosition()、. draw()、. moveTo()、. collideWith()などのメソッドがあるため、外部から直接値を取得または設定する必要はありません。
本当に外部から直接値を取得/設定したいというまれなケースがいくつかありますが、これらのインスタンスはまれであり、多くの場合、悪い設計を示しています(有効な使用法はありますが)。
私はゲッター/セッターを使用します。なんで ?
- カプセル化が重要です。おそらく、後で場所の保存方法を変更します(たとえば、デカルト座標から極座標に変更しますか?)。ゲッター/セッターを使用すると、適切な変換を実行できます。
- セッターは、オブジェクトが条件を適用できるようにします(たとえば、x> 0かつ<10?)
さらなる理由(おそらく現在のニーズには適切ではありませんが)は、多くのJavaフレームワークが、従来のsetX
/getX
形式のセッター/ゲッターのリフレクションおよびイントロスペクトクラスを利用していることです。このようなメソッドを実装することで、クラスをさまざまなフレームワークですぐに再利用できるようになります。
既知の懸念事項になるまで、パフォーマンスについて心配する必要はありません。時期尚早の最適化はあなたにあまりにも多くの頭痛を引き起こします。
Stendhalでは、ゲッター/セッターを使用します。毎ターン処理される約 60,000 個の可動オブジェクトがあります。Stendhal での私の経験から、シンプルなメソッドは測定可能なパフォーマンスへの影響はまったくありません。さまざまな問題を見つけるためにプロファイリングを少し静かにしましたが、ここ数か月でパフォーマンスが大幅に改善されました。
私たちが抱えている主なボトルネックは、経路探索 (特に他の可動オブジェクトとの衝突検出) です。可能性のあるすべての衝突チェックで新しい Pair オブジェクトを作成したり、Entity がその位置とサイズを求められるたびに新しい Rectangle オブジェクトを作成したりするなどの問題がありました。
これらのことは、プロファイラーで非常に簡単に見つけることができます ( gamedevの Java でのサーバー側ゲーム ループのプロファイリングを参照してください)。
ゲーム ループのロジック部分以外でラグが発生するその他の一般的な原因は、クライアント/サーバー通信とデータベース アクセスです。