Крайните членски променливи правят по-добър GC?

Този въпрос е продължение на този, но изисква по-конкретен сценарий.

Да кажем, че имаме следния клас:

public class Person {
    private Foot left, right;

    public Person(Foot left, Foot right) {
        this.left = left;
        this.right = right;
    }
}

Чудех се дали следният клас ще може да бъде оптимизиран от гледна точка на GC, ако го превърнем в следното:

public class Person {
    private final Foot left, right;

    public Person(Foot left, Foot right) {
        this.left = left;
        this.right = right;
    }
}

Ако гледах този клас, веднага мога да кажа, че лявата и дясната променливи никога не могат да бъдат зададени на нула рано. Това означава, че единственият път, когато GC ще трябва да събере левия и десния обект (и да намали препратките към него) за този клас, ще бъде, когато препратките към родителския клас Person достигнат нула. Това също трябва да означава, че може да е в състояние да събира хора в същото време, когато събира предмети от ляво и дясно стъпало; което също води до по-малко писти и ускоряване.

Следователно, в този пример, маркирането на променливите частен член като final означава ли, че кодът ще доведе дори до незначително ускоряване на събирането на отпадъци (или може да се използва като точка за ускоряване)?


person Robert Massaioli    schedule 07.06.2011    source източник
comment
отговорите в предишния въпрос изглежда доста категорично заявяват отговора като не - има ли част от тези отговори, която е неясна? Иначе този въпрос звучи почти по същия начин   -  person matt b    schedule 07.06.2011


Отговори (3)


Присвояването на полета не задейства никаква работа за събиране на боклук или корекция на броя на препратките, тъй като GC на Java не използват преброяване на препратки (*). Така че отговорът е, че декларирането на поле като final няма да промени производителността на събирача на отпадъци. (Фазата на проследяване на колектора трябва да провери полето дали е или не е final.

Възможно е декларирането на поле като final да помогне за анализа на потока от данни на JIT компилатора и оптимизирането на извличането на паметта. Въпреки това би било лоша идея да се използва това като оправдание за промяна на полетата на final. Ако възнамерявате да го направите, направете го от съображения за коректност (т.е. за да направите конструкцията безопасна в едновременен контекст) или от стилистични причини (т.е. за да направите кода по-лесен за разбиране и поддръжка).

(* Нито една основна реализация на Java не разчита на преброяване на препратки за прилагане на управление на паметта. Теоретично е възможно някой може да внедри JVM, използваща преброяване на препратки, но общоприетото мнение е, че преброяването на препратки е ужасно неефективно ... да не говорим за проблема за паралелност, цикли на събиране и т.н.)

person Stephen C    schedule 07.06.2011
comment
направете го по стилистични причини Това не звучи правилно. Настройването на крайни полета (обикновен начин, без отражение) е бариера за паметта, така че „времето за изпълнение (JVM)“ гарантира, че обектът е правилно конструиран и final field е правилно конструиран преди конструктора, ако е завършен. (гарантира видимост на паметта). това е много важно при многонишкови програми. - person Op De Cirkel; 07.06.2011
comment
Този отговор беше доста добър. ДОКАТО никой Java GC не използва преброяване на референции например. Въпреки че Op De Cirkel е прав като заявява, че крайните полета са полезни за осигуряване на неизменен обект. И знам, че настройката на полетата не задейства събиране на боклук, но какво ще кажете, когато обектът на лицето, някъде другаде в кодовата база е зададен на нула и е маркиран за събиране на боклук. Това не означава ли, че потенциално бихте могли да маркирате и двата крака за жътва? - person Robert Massaioli; 07.06.2011
comment
@Robert Massaioli - няма маркировка за сметосъбиране. Единствената маркировка е маркировка НЕ ​​за сметосъбиране. AFAIK, тук няма възможност за оптимизация. - person Stephen C; 07.06.2011
comment
Добре тогава. Благодаря за изчерпателния отговор и отбелязването като такова. - person Robert Massaioli; 07.06.2011

Единствената причина, поради която GC оптимизацията не е възможна, е защото JVM спецификацията позволява промяна на final поле.
final полетата имат специална семантика по време на процеса на конструиране на обекта, което е важно за правилната работа на процеса на конструиране по отношение на модела на паметта на Java. Но можете да нарушите правилата и да използвате отражение, за да го промените. В този случай не можете да разчитате на семантиката на полето final (по отношение на модела на паметта на Java)

стачката: Съжалявам момчета, не знам за какво говорех. final е без значение за GC. дори ако final изобщо не може да се променя, GC не може да получи полезна информация за този факт

person Op De Cirkel    schedule 07.06.2011
comment
това е хипотетично. Предполага се, че ще има някаква оптимизация въз основа на final полета ... което не е вярно. - person Stephen C; 07.06.2011

Събирането на боклука на Java не работи чрез преброяване на препратки. Той работи, като изследва обектите за достъпност.

person user207421    schedule 07.06.2011
comment
Събирането на боклука не работи, като се изследват обекти за препратки Как тогава може да работи? - person Op De Cirkel; 07.06.2011
comment
@Stephen C @Op De Cirkel Благодаря, преформулирано. - person user207421; 07.06.2011