forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Monkey (http://forum.boolean.name/forumdisplay.php?f=163)
-   -   Отрицательные моменты в Monkey (http://forum.boolean.name/showthread.php?t=18027)

SBJoker 26.03.2013 17:53

Отрицательные моменты в Monkey
 
Для того чтобы у всех сформировалось правильное представление об этом движке, надо добавить к плюсам и очевидные минусы.

Поехали:
  1. В Monkey нет такого понятия как Деструктор. Сам Марк пишет в хелпе что всё заменяет сборщик мусора, и всё что нам нужно это присвоить Null объекту. И вот тут и кроется противоречие. Если в вашем классе есть поля являющиеся объектами (данные по ссылке), то при удалении объекта класса этим полям так же нужно присвоить Null, иначе сборщик мусора их не заметит. Обычно это делается в деструкторе, где программист указывает как правильно удалить связанные данные. Причём этих проблем полны стандартные модули. Например:
    Цитата:

    Local myImage:image = LoadImage("someimage.jpg")

    'free memory by Mark's solution
    myImage = Null

    'memory leak
    Память утекает потому что внутри класса image есть поля ссылающиеся на текстуру, и их надо обнулить вручную. Благо Марк таки предусмотрел метод который это сделает, но вызывать его надо вручную до обнуления самой картинки так:
    Цитата:

    myImage.Discard()
    myImage = Null
    Вот такой вот костыль, а стоило сделать чтобы все методы Delete или Discard были деструктора и вызывались сами при обнулении - было бы всё красиво. Однако проблема куда глубже чем одна дополнительная строчка при удалении картинки: если мы загрузим картинки и будет хранить их в списке, то возможно нам захочется удалить их все просто воспользовавшись методом Clear списка. Который уничтожает все элементы. Однако опять же кто будет вызывать Discard() у каждой картинки? Fail
  2. Нет никакого нормального способа получить доступ к пикселям картинки. Только через граббинг бэкбуфера, что имеет такие побочные эффекты как отсутствие изначальной альфы, необходимость делать граббинг в событии OnRender, и ограничение на размер картинки - не превышающий размеры этого самого бэкбуффера который обычно равен текущему разрешению экрана/окна
  3. Очень большие ограничения на свободное чтение/запись файлов. В основном Monkey предлагает загружать файл одним махом и потом работать с результатом, рандом же доступ к файлам обычно осложнен или вовсе запрещен (особенно это странно при доступе на чтение).
  4. Отсутствие вообще какой либо поддержки работы с файловой системой. Небольшая поддержка имеется лишь у пары таргетов.
Продолжение следует

devolonter 26.03.2013 19:41

Ответ: Отрицательные моменты в Monkey
 
Объективные и верные замечания. Хотел только немного уточнить ситуацию под Discard.

Этот метод нужно использовать только тогда, когда вы больше не планируете использовать высвобождаемый ресурс, совсем. Т.к. в противном случае, при обращении к изображению ссылающемуся на ресурс, который был высвобожден из памяти вы получите ошибку. Именно поэтому не всегда удобно и практично добавлять этот метод в деструктор. Лучше, чтобы этим занимался менеджер ресурсов

Например:
Код:

Local myImage:image = LoadImage("someimage.jpg")
Local myImage2:image = myImage

myImage.Discard()
myImage = Null

'ошибка
DrawImage(myImage2, 0, 0)

Так, ошибки не будет (утечки памяти тоже не будет):
Код:

Local myImage:image = LoadImage("someimage.jpg")
Local myImage2:image = myImage

myImage = Null

DrawImage(myImage2, 0, 0)

myImage2.Discard()
myImage2 = Null

Также, нет смысла вызывать Discard для изображений полученных через GrabImage. т.к. эти изображения хранят только ссылку на источник, а не новую копию ресурса. Mojo это учитывает и игнорирует высвобождение ресурсов.

Discard помимо изображений нужно вызывать также и для звуковых файлов. Опять таки только в том случае, если больше не планируете использовать данные ресурсы.

SBJoker 26.03.2013 20:39

Ответ: Отрицательные моменты в Monkey
 
Ну это всё понятно, класс image был приведен как пример от Марка. На самом деле для вообще любого класса верно то что перед удалением объекта класса нужно обнулить все поля являющиеся объектами (т.е. не примитивными типами данных) включая массивы. И это явно указывает на отсутствие деструкторов как понятия.

moka 26.03.2013 20:44

Ответ: Отрицательные моменты в Monkey
 
Вопрос относительно этих ссылок: это относится только к медии, или также распространяется на объекты в коде? Или же Марк всё таки реализовал глубокое сканирование на ссылки для сборщика?
UPD
Цитата:

Сообщение от SBJoker (Сообщение 255826)
Ну это всё понятно, класс image был приведен как пример от Марка. На самом деле для вообще любого класса верно то что перед удалением объекта класса нужно обнулить все поля являющиеся объектами (т.е. не примитивными типами данных) включая массивы. И это явно указывает на отсутствие деструкторов как понятия.

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

Относительно файлов - тут всё очевидно же, работа с файлами не только отличается по функциям и правам доступа на разных платформ, но и ещё хуже совсем другими принципами работы с файлами, что объединить под одним представлением будет очень сложно, скорее всего это приведёт к куче кривых дополнений по конверсиям и т.п. например в бинарный вид, и ещё чего похуже..

devolonter 26.03.2013 20:51

Ответ: Отрицательные моменты в Monkey
 
Цитата:

Сообщение от SBJoker (Сообщение 255826)
Ну это всё понятно, класс image был приведен как пример от Марка. На самом деле для вообще любого класса верно то что перед удалением объекта класса нужно обнулить все поля являющиеся объектами (т.е. не примитивными типами данных) включая массивы. И это явно указывает на отсутствие деструкторов как понятия.

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

jimon 26.03.2013 21:54

Ответ: Отрицательные моменты в Monkey
 

Цитата:

ой нимагу жить без супер умного GC, говно говно говно
скока можно же

Randomize 26.03.2013 22:03

Ответ: Отрицательные моменты в Monkey
 
Какой сборщик? В каждом таргете тупо юзается свой сборщик вот и всё.

Пишем на мартышке - js|as|c#|c++,gcc в уме.

moka 26.03.2013 22:43

Ответ: Отрицательные моменты в Monkey
 
Цитата:

Сообщение от Randomize (Сообщение 255836)
Какой сборщик? В каждом таргете тупо юзается свой сборщик вот и всё.

Пишем на мартышке - js|as|c#|c++,gcc в уме.

Ну по сути можно было бы и реализовать абстракцию деструкторов для всех платформ, что решило бы проблему, как предложил SBJoker.

devolonter 26.03.2013 23:20

Ответ: Отрицательные моменты в Monkey
 
Цитата:

Сообщение от MoKa (Сообщение 255841)
Ну по сути можно было бы и реализовать абстракцию деструкторов для всех платформ, что решило бы проблему, как предложил SBJoker.

Так как не все языки поддерживают деструкторы, то единственный выход который я вижу - на уровне транслятора, во время транслирования, добавлять вызов деструктора перед = Null. Например есть следующий код,

Код:

a = Null
После трансляции получаем:
Код:

If (a <> Null) a.Destroy()
a = Null

Но это далеко не самый оптимальный подход. Чтобы избежать лишних вызовов по мне лучше самому контролировать этот процесс (в данном случае). Можно написать свой деструктор, просто не забывать его вызывать, вот и все.

YellowAfterlife 02.04.2013 21:34

Ответ: Отрицательные моменты в Monkey
 
Цитата:

Сообщение от devolonter (Сообщение 255847)
<snip>

Проблемы сборщика мусора это проблемы сборщика мусора.
А если он не проверяет связи между переменными, то он уже не совсем то и сборщик.

Приведенный метод вроде бы и работает, но на самом деле порождает еще большее количество проблем.
Рассмотрим, к примеру, такой случай:

Есть некий глобальный assets, в котором хранятся загруженные ресурсы (дабы память не переводить дубликатами тех же изображений).
Мы загружаем на старте игры в него изображения:
Код:

assets.circle_png = LoadImage("circle.png")
assets.dog_png = LoadImage("dog.png")
' (и так далее)

Так же допустим, что у нас есть некий класс объекта, отображающего изображение из своей переменной (как PictureBox в NET/VCL/...).
И мы делаем подобную манипуляцию:
Код:

' Загружаем изображение в элемент 1:
picture1.image = assets.circle_png
' Загружаем изображение в элемент 2:
picture2.image = assets.circle_png
' После, к примеру, нам нужно выгрузить изображение
' из элемента 1. Может быть это деструктор, может
' нам просто нужно убрать из него изображение...
picture1.image = null
' И тут программе приходит конец: мы только что
' успешно выгрузили из памяти изображение, которое
' еще используется в элементе 2.

Конечно же, можно было бы сделать подсчет ссылок, и вызывать деструктор при потере последней ссылки на экземпляр, но это возвращает к ранее упомянутой проблеме того, что в JS и AS модифицировать сборщик мусора нельзя вовсе.

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


Часовой пояс GMT +4, время: 19:41.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot