簡體   English   中英

吸氣劑是否對Java性能不利?

[英]Are getters bad for performance in Java?

給定以下兩個代碼選項,與第一個相比,第二個代碼在性能上有很大的好處嗎(在非常大的規模或很長的一段時間內)?

選項1

private Map<Long, Animal> animals = ...;
public Map<Long, Animal> getAnimals() {
    return animals;
}

public void useAnimals() {
    for (int i=0; i < SOME_LARGE_NUMBER; i++) {
        Animal animal = getAnimals().get(id);
    }
    // Many many calls to getAnimals() are made...
}

選項2-無吸氣劑

private Map<Long, Animal> animals = ...;

public void useAnimals() {
    for (int i=0; i < SOME_NUMBER; i++) {
        Animal animal = animals.get(id);
    }
    // No method calls made
}

如果對性能不利,為什么?如何確定它是否值得緩解?

並且,將getAnimals()的結果存儲為本地會帶來好處...

  • SOME_NUMBER是幾百還是幾千?
  • 如果SOME_NUMBER的數量級僅為10?

注意 :我之前說過“封裝”。 我將其更改為“ getter”,因為實際上的目的不是要修改字段,而是不能重新分配字段。 封裝只是為了消除子類分配的責任。

JVM最有可能在緊密循環中內聯getAnimals()調用,從而有效地退回到Option 1 因此,不要打擾,這實際上是一個微(納米)優化。

另一件事是從字段訪問遷移到局部變量。 這聽起來不錯,因為不必每次都在堆棧上始終有一個引用時遍歷this引用(兩個內存訪問相對於一個)。 但是,我相信(如果我錯了,請糾正我),由於animals是私有的並且是非易失volatile ,JVM將在運行時為您執行此優化。

第二個摘要比第一個摘要封裝得更多 第一個將任何人都可以訪問內部映射,而第二個將其封裝在類中。

兩者都會帶來可比的性能。

編輯:由於您更改了問題,我也會更改答案。

如果您經歷了一個吸氣劑,而該吸氣劑不是最終的,則意味着子類可能返回與您在類中持有的映射不同的另一種映射。 選擇您要讓方法在子類的地圖上還是在類的地圖上進行操作。 兩者都可以接受,具體取決於上下文。

無論如何,假設您的子類總是制作地圖的防御性副本,如果您不將getter的結果緩存在useAnimals的局部變量中,最終將擁有許多副本。 可能需要始終處理子類映射的最新值,但我懷疑情況確實如此。

如果沒有子類,或者子類沒有重寫該方法,或者不通過始終返回相同的映射來重寫該方法,則兩者都將導致可比的性能,因此您無需理會。

您是否配置了此文件以查看是否重要,對於現代JIT,我它會受到影響,特別是如果將animals標記為final animals ,但是沒有什么阻止您自己對此進行測試。

無論哪種方式,我都100% 決不成為您在應用程序中的瓶頸。

好吧,我認為JVM不會內聯函數調用。 因此可能會影響性能。 更好的方法是創建局部變量並為其分配類字段動物。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM