2009-06-21 7 views
4

Я программировал в ActionScript около 6 лет, но никогда не слышал о терминах «сбор мусора» до тех пор, пока AS3 не выйдет. Почему мы должны беспокоиться об этом сейчас и никогда раньше? И что именно? Из того, что я читал/слышал, это имеет какое-то отношение к управлению памятью/утечкам и т. Д. - и даже , что Я не очень понимаю, кроме того, что это имеет какое-то отношение к производительности.Что такое сборка мусора и как вы это делаете в ActionScript 3.0?

Недавно я запустил сайт для моего друга-художника, и это было сделано в AS3. Я замечаю, что он берет много ресурсов. Очевидно, это то, что я хотел бы улучшить. Я предполагаю, что это имеет какое-то отношение к тому факту, что сбор мусора не происходит ?! К сожалению, я не имею ни малейшего представления о том, с чего начать в отношении этого, поскольку я чувствую, что мне нужно лучше понять, что это такое и как делать это специально в AS3.

Для любопытных, вот URL: http://www.jeffperrott.com

ответ

0

Я ничего об осуществлении Ap3 не знаю, но кто-то должен этот пост :)

http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

В принципе, вы работаете с указателями (ну, ссылки) на данные. Ссылка, выходящая за пределы области действия, будет удалена. Всякий раз, когда никакие ссылки не указывают на данные, данные будут помечены для сбора мусора. Ваш GB-поток (процесс или демон) вовремя освободит все ресурсы, используемые для выделения помеченных данных.

0

Обычно вы, или ваша среда разработки, должны вручную обрабатывать память в какой-то момент, увядать, чтобы создать пространство для данных ваших приложений в памяти или очистить память от использования, как только ваше приложение будет выполнено с ним. Если в рабочей среде нет GC (сборщик мусора), вам необходимо вручную обрабатывать творения и удалять пространства памяти для ваших переменных и объектов в вашем приложении.

Примером является родной C++. До того, как программисты на C++ действительно могут многое сделать с приложением, они должны сделать основную работу, которая касается самой памяти. Они запрашивают ОС для памяти, добавляют добавления, добавляют объекты и данные в память, потом удаляют объекты и данные, нераспределяют память, очищают ее и снова выпускают в ОС.

С GC GC делает все, что сработает для вас. Все, что вы делаете, это сообщить GC (обычно путем создания объекта), что вы планируете использовать память, а GC вычисляет, сколько памяти вам нужно, спрашивает ОС для нее, выделяет и добавляет ваши данные. Затем он проверяет время от времени, если ваше приложение все еще использует этот объект. Если это не так, он удаляет объект, нераспределяет, очищает его и освобождает обратно в ОС. Все это делается для вас, чтобы вы, программист, могли просто сосредоточиться на своей программе. Примером этого является VB 6.0 и C#/VB.NET.

EDIT: Это чрезвычайно упрощенное объяснение. На самом деле это гораздо больше, но этот ответ должен ответить на основной вопрос, заданный здесь.

6

Сборщик мусора является частью среды выполнения (в вашем случае проигрывателя Flash или AIR), которая очищает неиспользованную память. В ActionScript всегда была сборка мусора, такая как все языки сценариев (например, javascript, perl, ruby ​​и т. Д.), Вы просто не видите, что это много обсуждается для AS.

Основная идея состоит в том, что каждый созданный объект занимает некоторую память, а ваши переменные сохраняют ссылку на эти объекты. Память объекта не «высвобождается» обратно в пул доступной памяти, пока на ней больше нет ссылок.Сборщик мусора отслеживает, какие объекты имеют ссылки на них, и с различными интервалами восстанавливает память тех, у кого нулевые ссылки (т. Е. Нет переменных, указывающих на него, поэтому ни один код не может даже найти его для его использования). Если есть какие-либо ссылки *, память объекта не может быть исправлена, если какая-то часть вашего кода решит использовать ее в будущем.

Если ваша программа, по-видимому, протекает в памяти (постоянно растет, никогда не стабилизируется по размеру или уменьшается), возможно, вы размещаете объекты в хеше или массиве или в каком-либо другом объекте коллекции. Этот объект, очевидно, поддерживает ссылку на его содержимое, поэтому эти вещи никогда не удаляются.

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

function registerHandler(neverReleased:Object) { 
    ... 
    addEventHandler(function (e:Event) { 
      ... 
     }); 
} 

Вызов сборщика мусора непосредственно почти всегда плохо (тм), сборщик мусора в Flash/Flex очень хорошо. Сначала узнайте, где хранятся ваши объекты, и отпустите их, позволяя GC работать в своем собственном расписании.

* За исключением circular references, который немного отличается от сферы действия этого ответа.

0

Добавление к ответу Чадвика:

Если вы addEventHandler к изображению, но не не removerEventHandler, когда уже не будет отображаться изображение, память, занятая изображение не может быть восстановлена ​​с помощью сборщика мусора.

+0

В AS3 вы можете создать слабую ссылку на прослушиватель событий, который позволит отображать изображение (например) для сбора мусора. –

+0

Это addEventListener, и это наоборот. Функция, прослушивающая событие, не будет собираться, пока изображение существует. –

+0

Вы абсолютно правы. Спасибо, что указал на мои ошибки. –

2

Каждый раз, когда вы используете «новое» ключевое слово для создания объекта, вы ставите свою заявку на кусок памяти [1]. Итак, скажем, вы делаете uint, написав var exampleUint:uint = new uint();. ActionScript говорит компьютеру «эй ... Мне нужно ... четыре байта памяти», на который компьютер отвечает «хорошо, используйте четыре байта, начиная с [некоторого адреса памяти, например 0x7B3208C1]» [2] , Поэтому, когда вы говорите var someString:String = "blah";, вы претендуете на пробел в памяти, заполните его некоторой информацией (в данном случае это "blah"), создайте метку (в данном случае это someString) и bind ярлык для этого пространства в памяти.

Теперь метка фактически не связывается с самими данными, она связывается с местом в памяти, содержащей данные. Это должно показаться запутанным, потому что это так, но по определенным причинам оно вызывает целомудренное чувство. Все объекты в ActionScript имеют значения reference, что означает, что объект содержит адрес памяти некоторой части данных, а не самих данных. Это контрастирует с объектами, которые являются типами value, где метка ассоциируется с самими данными. Не волнуйтесь о деталях типов значений, потому что это не в ActionScript, поэтому для ваших целей я включаю его строго для контраста. Хорошо, смущенный? Вы, вероятно, должны быть, потому что весь этот абзац совершенно бесполезен и, возможно, даже ненужен, но старайтесь держать его в задней части головы, потому что может иметь какое-то отношение к вашей проблеме.

Теперь, когда эта метка исчезла (например, она выходит из scope, так что теперь someString не имеет смысла), удаляется только метка someString. Итак, для этого примера, если вы скажете someString = null;, строка "blah" на самом деле все еще в памяти, но метка someString не ссылается на эту часть информации, она ссылается на адрес памяти the null object (опять же, подробности). Нам нужен способ указать на компьютер «вы знаете, что [whatSize] кусок памяти, который я утверждал, начиная с [whateverAddress]? Хорошо, я закончил с этим сейчас, чтобы кто-то еще мог использовать эту часть памяти».Gabage collection - это автоматический процесс восстановления памяти, о котором вы заявили, не беспокоясь об этом самостоятельно. На языках без сбора мусора new имеет ключевое слово дополнения, которое специально освобождает память, связанную с объектом [3], но ActionScript не имеет этого; вы просто возьмете кусочек памяти и забудете об этом.

Где-то вдоль линий вы могли создать другую переменную и ссылались на эту часть данных, var someOtherString:String = someString;, поэтому мы не можем просто сказать «хорошо», метка someString ушла, поэтому давайте избавимся от данных, которые она ссылается », потому что мы точно не знаем, что someString является единственной ссылкой на эти данные. Метод, в котором это делается, варьируется между языками и системами сбора мусора, но основная сделка в ActionScript такова: время от времени (особенно если Flash в настоящее время занимает много памяти), сборщик мусора просматривает все объектов в текущем SWF и находит все объекты, которые не имеют ссылки [4]. Итак, для нашего предыдущего примера, если someString было единственной вещью, которая ссылалась на строку "blah" и someString, выходит за пределы области видимости, то "blah" не связан ни с одной меткой и поэтому полностью недоступен для Flash. В следующий раз, когда сборщик мусора запустится, он найдет это, а затем сообщит в систему, что это делается с этой частью памяти.

Теперь конкретные детали вашей конкретной проблемы трудно сказать, не глядя на источник, но я могу сказать вам, что одна из вещей, которая часто вызывает проблемы, - это прослушиватели событий. Иногда вы можете создать функцию и добавить ее в качестве прослушивателя событий. Теперь само событие имеет ссылку на эту функцию [5], поэтому, если функция выходит за пределы области видимости, она все еще ссылается на нее, и функция не получает сборщик мусора (помните, что функции являются объектами в ActionScript). Вы можете либо удалить обработчик событий вручную, вызвав removeEventListener (я бы не рекомендовал его), либо установить параметр useWeakReference при звонках на addEventListener() до true. Слабая ссылка не распознается сборщиком мусора, поэтому установка useWeakReference на true предотвращает ситуацию, когда у вас есть функция, которую должен быть, собранный сборщиком мусора, но это происходит не потому, что кто-то ссылается на него как на прослушиватель событий , Судя по большому количеству слушателей mouseEvent в вашем проекте, это может быть преступником. Если у вас есть Flex Builder, вы можете использовать профилировщик, чтобы узнать, сколько у вас закрытий методов; если они поднимаются и никогда не спускаются, это, вероятно, ваша проблема.

[1]: Имейте в виду, что это также относится к ситуациям, в которых вы создаете объект, не используя ключевое слово new, например, если вы должны были написать var exampleInt:int = 5;.
[2]: Я выбрал uint, потому что все uints имеют одинаковый размер, поэтому я могу с уверенностью сказать, что знаю, что это будет четыре байта. Строки разные; они занимают объем памяти, пропорциональный количеству символов, которые они содержат, поэтому было бы немного более двусмысленно использовать String для обоих примеров.
[3]: Ключевое слово ActionScript delete не для этой цели, поэтому не пытайтесь использовать его таким образом, хотя это будет иметь логический смысл и было бы очень полезно.
[4]: ​​Flash использует стратегию стиля mark-and-sweep, более конкретно подробную информацию о которых можно прочитать here. [5]: На самом деле, это жирный шрифт, потому что метод addEventListener использует closures, но у меня есть довольно слабое понимание этого для начала, поэтому я не могу действительно сварить его на обычного человека.

0

Просто, чтобы помочь вам понять, почему вы не слышали об этом раньше, в предыдущих версиях AS GC был глубоко связан с отображаемым списком. Как только вы удалили объект из сцены, он больше не существовал (вместе с любыми дочерними объектами), и любая ссылка на них была обращена в нуль.Такое поведение, как вы уже знаете, в AS3 совершенно противоположное. Удачи!