2016-02-13 4 views
15

私はnewbです。私は最初の2つの回答hereからガベージコレクションについて読んでいます。不変オブジェクトはガベージコレクションのためにオーバーヘッドをどのように減らすのですか?

プログラマが新しいオブジェクトを作成しなければならない場合でも、マルチスレッドアプリケーションで既存のオブジェクトを使用するのと比較して、this tutorialはオブジェクト作成のコストがガベージコレクション、およびスレッド干渉及びメモリ一貫性エラーから可変オブジェクトを保護するためのコードの除去にメモリオーバーヘッドの減少:

オブジェクト作成の影響をしばしば過大評価され、そしていくつかによって を相殺することができます不変オブジェクトに関連する効率。 これらは、ガベージコレクションによってオーバーヘッドが減少したと、 の破損から変更可能なオブジェクトを保護するために必要なコードが削除された を含みます。

質問はどうですか?ガベージコレクションはオブジェクトの変更または不変性と何が関係していますか?

+3

現代GCは、 "若く死んでいる"オブジェクトでは非常に効率的です。寿命が短いオブジェクトを作成して使用することを恐れないでください。より長い時間(例えば、キャッシングのために)オブジェクトを参照し続けることに注意してください。この問題は、実際には不変性に関するものではなく、寿命に関するものです。 – ZhongYu

+1

リンクしたチュートリアルでは、正確なフレーズは_ "ガベージコレクションのためにオーバーヘッドが減少しました" _です。そこには「記憶」という言葉はありません。それにもかかわらず、不変のオブジェクトは実際にはより多くのメモリを消費する可能性があるため(既存のもので変更したい場合は新しいものを作成する必要があるため)、問題の修正を行う必要があります。詳細は以下の私の答えです。 –

答えて

11

オブジェクトが不変の場合は、時には割り当てが少なくなることがあります。

簡単な例

Date getDate(){ 
    return copy(this.date); 
} 

私はそれが可変であるか、呼び出し側がそれを変異させることができるようになるので、私はそれを共有するたびにDateをコピーする必要があります。 getDateたくさん呼び出される場合は、配分率が劇的に増加し、これは一方GC

に圧力をかけることになり、Javaの-8日付が、私は必要としないことを

LocalDate getDate(){ 
    return this.date; 
} 

お知らせ不変です(私はあなたがそれを変更することはできないことを知っているので、私はあなたとオブジェクトを共有することを喜んで)不変のために日付をコピーする(新しいオブジェクトを割り当てる)。

これを "有用な"または複雑なデータ構造に適用するにはどうすればよいでしょうか(防御的なコピーによる)、あなたは絶対に正しいですが、functional programmingpersistent data structuresというアートがあります実際にコピーがオリジナルから多くを共有する新しいコピーであるという錯覚を得る)。

ほとんどの関数型言語(私が知っているものすべて)がガベージコレクションされていることに驚かされるべきではありません。

+0

ありがとうございます。最後の2つの段落以外の答えは私にはっきりとしていましたが、私は最後の2つの段落をあまり理解できませんでした。あなたは時間があればそこにいくつかの光を投げることができます、そうでなければそれはいいです。答えをもう一度ありがとう。 – Solace

+0

@Solaceあなたは機能的なデータ構造を知っていますか?彼らは "素朴な"防衛的なコピーを避けるために多くのトリックを行います。 –

+3

@Solace 1つの(非常に単純な、古典的な)例はリストです。 '[a、b、c、d、e]'リストの場合、このリストから最初の2つの要素を ""削除できるように、この(不変の!)データ構造を実装することができます。 **新しいリストを作成したり、実際に既存のリストを変更したりしない**。代わりに、最初のものと同じメモリがバックアップされている "サブリスト" [c、d、e]を取得します。 https://en.wikipedia.org/wiki/Persistent_data_structureと関連するstackoverflowに関する質問も参照してください。 – Marco13

8

変更不可能なオブジェクトは、コンテキスト(信頼できない呼び出しコード)やスレッドの安全性のためにそれらを共有する場合、防御的なコピーを必要としません。これは、不変オブジェクトの読み込みがごみの点でより低くなる可能性があることを意味します。

一方、不変オブジェクトを変更するたびに、この必要があるかどうかに関係なく、新しいオブジェクトを作成する必要があります。これに関して、不変オブジェクトは、はるかに多くのゴミを生成する可能性があります。

実際の質問は、たくさんの書き込みをしているのか、それともたくさんの書き込み(ミックス)をしているのかです。使い方によっては、不変のオブジェクトはオブジェクトを保存したり、オブジェクトをさらに作成したりすることができます。あなたの特定のユースケースで。

注:ほとんどの場合、正確さはパフォーマンスよりはるかに重要であり、一般的に不変オブジェクトはオーバーヘッドの高いIMHOを持っていますが、不変オブジェクトを使用するデータモデルの正確性を証明するのはずっと簡単です。明快さと推論の容易さのためだけに不変オブジェクトを使う価値があります。

+2

私はその例のために他の回答を受け入れたものとしてマークしなければなりませんでしたが、アドバイスに感謝しています。それは私にとって貴重です。本当にありがとうございました。 – Solace

5

this articleブライアン・ゲッツはうまく説明します。基本的にはガベージコレクタの動作に関係しています。新しいオブジェクトが古いオブジェクトを参照する場合は、古いオブジェクトを参照する場合に行う作業が少なくなります。以下の例のクラスとリンク先の記事から

抜粋:ほとんどのケースで

public class MutableHolder { 
    private Object value; 
    public Object getValue() { return value; } 
    public void setValue(Object o) { value = o; } 
} 

public class ImmutableHolder { 
    private final Object value; 
    public ImmutableHolder(Object o) { value = o; } 
    public Object getValue() { return value; } 
} 

、ホルダーオブジェクトが 別のオブジェクトを参照するように更新され、新しい指示対象は、若いオブジェクトです。 setValue()を呼び出して MutableHolderを更新すると、古いオブジェクトが新しいものを参照する状況 が作成されています。一方、新しいImmutableHolderオブジェクトを で作成すると、古いオブジェクトは になります。

ほとんどのオブジェクトが古いオブジェクトを指している後者の状況は、世代別ガベージコレクタでは、はるかに優しい です。古い世代にある MutableHolderが変更された場合、MutableHolderを含むカード上の オブジェクトはすべて、次のマイナーコレクションで古くから若い参照の場合は にスキャンする必要があります。

長寿命コンテナオブジェクトの可変参照の使用 は、コレクション 時に古いものから若い参照を追跡するために行われる作業を増加させます。

オブジェクトの多くが作成されていることを懸念についてエスケープ分析

あなたは既存のものを変更する必要があるたびに新しいオブジェクトをインスタンス化しているため、オブジェクトの割り当て機構は、多くの最新のJVMに改善されています。

escape analysis(リンクされている記事にも記載されています)をご覧ください。多くのオブジェクトはヒープには割り当てられません(しかしスタックにインライン/アロケートされる)ので、GCはそれらとは何の関係もありません(実際にGCはそれらのオブジェクトが全く存在しないことを認識しません)。

エスケープ解析メカニズムは、不変のコンテキスト(リンクされたOracleドキュメントのメソッド呼び出し中に変更されていないPersonオブジェクトです)でより効率的に利用できます。

+1

不変性に厳密に関連するものではありませんが、キーワード** "エスケープ分析" **は、この文脈で実際に指摘する価値があります(私はそれ自身の答えを作成しましたが、にリンク)。 +1 – Marco13

関連する問題