2013-08-18 3 views
2

Есть кусок моего кода, который вызывается многократно (2000+ каждую секунду). Чтобы избежать генерации мусора и снизить накладные расходы на производительность, я переместил все локальные переменные на уровне класса, но я не уверен, что этот подход эффективен ...Локальные переменные и вывоз мусора

Мой вопрос ...

  • Когда локальные переменные собираются сборщиком мусора?
  • Выполняет ли перемещение локальных переменных на уровне класса и повышает производительность мусора?
+0

Можете ли вы предоставить образец того, как выглядит метод? – jrbeverly

+0

Вы что-то измеряли? Я бы сказал, что превращение локальных варсов в поля будет медленнее и кошмаром для нарезки. Но это зависит. –

+0

Никаких мер не сделано, и это действительно пронизанный ночным кошмаром, также он может потреблять больше памяти на объект, и это может замедлить распределение первоначального объекта в памяти, но уменьшает ли он генерацию мусора или повышает производительность? используя уже выделенную память для критических по времени методов. – Fadi

ответ

2

Рассмотрим очень простой пример (где SomeObject класс, а не структура):

class C 
{ 
    void MethodCalledMillionsOfTimes() 
    { 
    var so = new SomeObject(); 
    // some use of so 
    } 
} 

Каждый раз, когда вызывается метод, один новый объект создается на куче. Он должен быть собран мусором некоторое время после того, как его использование закончилось. Это один объект для сбора за вызов метода.

Тогда предположим, что он превращается в:

class C 
{ 
    SomeObject soField; 

    void MethodCalledMillionsOfTimes() 
    { 
    soField = new SomeObject(); 
    // some use of soField 
    } 
} 

Это ничего не меняет! Вы по-прежнему создаете один новый экземпляр для каждого вызова метода. Сборщик мусора должен выполнять ту же работу.

Но что, если вы сделали:

class C 
{ 
    SomeObject soField = new SomeObject(); 

    void MethodCalledMillionsOfTimes() 
    { 
    // some use of soField 
    } 
} 

На этот раз тот же объект повторно используется каждый раз, когда метод вызывается снова на том же экземпляре. Таким образом, меньше объектов нужно собирать мусор (предполагая, что метод фактически вызывается много раз на том же объекте C). Обратите внимание, что это может работать только в том случае, если экземпляр SomeObject может использоваться много раз и не имеет своего состояния «разрушен» при каждом использовании.

Если многие потоки вызывают метод сразу, убедитесь, что объект soField может справиться с этим.

Если вы идете дальше и сказать:

class C 
{ 
    static SomeObject soStaticField = new SomeObject(); 

    void MethodCalledMillionsOfTimes() 
    { 
    // some use of soStaticField 
    } 
} 

то есть только один объект разделяется между всеми экземплярами C.No SomeObject должен быть собран GC.

Однако эта деятельность GC очень часто не важна для вашей работы. Поэтому, пожалуйста, меры, если это важно или нет в вашем случае.

+0

Это просветление, особенно для объектов и массивов (ссылочные типы), но как насчет типов значений ...? – Fadi

+0

@Fadi Как правило, если вы объявляете локальные переменные типа значения внутри некоторого метода (и если эти локальные переменные не захватываются анонимным методом или подобными вещами и если они являются «простыми» типами значений, которые не содержат ссылок внутри самих себя), то эти значения просто помещаются в стек и снова вылетают из стека, поэтому сборщик мусора не работает там. Точно так же, обновляя значение поля типа значения существующего объекта, не будет создавать никаких новых объектов, требуемых сборщиком мусора. –

14

Переменные не собираются с мусором. Объекты собирают мусор ... и они могут быть собраны в любое время после того, как среда выполнения может обнаружить, что они больше не ссылаются на какой-либо живой код. Это может включать в себя объекты, указанные локальные переменные:

public void Foo() 
{ 
    object x = new object(); 
    // The object can't be collected here... 
    Console.WriteLine(x); 
    // But it *can* be collected here 
    Console.WriteLine("This line doesn't depend on x"); 
} 

Это очень редко хорошая идея, чтобы изменить «естественный» дизайн ради сбора мусора ... то, что является состояние метода не является, как правило, естественно частью состояния объекта, поэтому включение локальной переменной в переменную экземпляра обычно является плохим.

При этом мы не знаем, что представляют собой эти локальные переменные, или что-то в этом роде - нам нужно больше контекста, чтобы комментировать ваш случай.

+0

И повторное использование экземпляров, которые он может захотеть сделать, сложнее, чем он понимает. – SLaks

+0

На самом деле, нет конкретного случая, это просто подход, о котором я не уверен, я стараюсь избегать выделения и де-распределения переменных в очень чувствительной и повторяющейся части моего графического движка в реальном времени. – Fadi

+1

@Fadi: Ваш вопрос * прозвучал * очень специфично: «Есть кусок моего кода, который вызывается многократно (2000+ каждую секунду). Чтобы избежать генерации мусора и снизить накладные расходы, я переместил все локальные переменные на уровень класса" - Как это не конкретный случай? –