Re: Garbage collection vs manual memory management
От: vsb Казахстан  
Дата: 08.01.15 11:33
Оценка: +10
Если у тебя бардак в программе и ты не знаешь, кто куда указывает, то это бардак, а не недостатки GC. Причём даже в твоём use-case GC выигрывает. В самом худшем случае ты получишь утечку памяти. Что ты получишь в C++ – вообще никто не знает, в лучше случае падение.
Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 08.01.15 10:01
Оценка: 22 (1) +1 -1 :)))
Сразу скажу тут скорее не то что вы ожидаете, это не очередной вброс о производительности программ написанных на C# и C++.


Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.
А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.

Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.

Я сам С++ник и безуспешно пытался пересесть на С#. Я поимел реальных проблем с тем что я впринципе не имею никакого контроля над временем жизни объектов мной созданных. К примеру загрузил я файл в модель, отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств. Всё что тут можно сделать это подчистить везде везде везде ссылки на эту форму, на модель и скрестить пальцы что скоро всё само удалится. И всё равно не срабатывает в 50% случаях.

Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.
Re[3]: Garbage collection vs manual memory management
От: Sergey J. A. Беларусь  
Дата: 08.01.15 11:07
Оценка: +6
J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.

J>Я об этом и говорю что тут токо сиди и надейся что оно сработает, нет в языке средств прямого управления временем жизни объекта.


А в плюсах что будет? Указатель на мусор?
Re[9]: Garbage collection vs manual memory management
От: __kot2  
Дата: 18.01.15 19:01
Оценка: -5 :)
Здравствуйте, gandjustas, Вы писали:
__>>Здравствуйте, gandjustas, Вы писали:
G>>>Тогда приведи минимальный код, который падает по этой причине. На .NET.
__>>да просто открытие файлов в цикле должно падать
G>Проверь
G>
G>static void Main(string[] args)
G>{
G>    for (int i = 0; i < 1000000; i++)
G>    {
G>        new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
G>    }
G>}
G>

G>Не падает
ну, в общем-то интересная задачка наверное. я бы чтобы добиться падения попробовал бы рандомное имя файла давать и еще что-нить читать оттуда, чтобы гарантировать открытие. а то вдруг оно там ленивое? или в оптимизаторе дотнетовском стоит каколй-нить if — типа в цикле если файлы открываем, но не читаем, то не открывать их

__>>если хотите просимулировать то, о чем я говорю — вставьте в начала частоиспользуемых ф-ий вашего приложение по открытию файла и оно у вас начнет непрдесказуемым способом падать в разных местах по out of resources

G>Не будет.
я сам сталкивался недавно с этим. создаешь просто пару сотен потоков и начинаешь в них что-то делать. у тебя то там, то там out of resources

G>Ты только что расписался, что не знаешь как работает GC и .NET вообще.

а он что, может отловить когда handle закончились? он смотрит на оставшуюся память. откуда он знает, что у нас еще и лимит по хэндлам или там, потокам?
раньше был лимит по файловым хэндлам вроде около 5000, сейчас по-моему его тысяч до 100 увеличили как раз по причине что падает вся Явовское-дотнетовское. ну да, решение в духе этих языков. есть же другие лимиты — на потоки, на графические примитивы, на, там, кто его знает что еще. не только в обьеме памяти дело.

__>>понимаете, что вы просто вручную уничтожаете обьект? не бывает никаких init и dispose. бывает создание и уничтожение обьекта. а то, что оно разбито на два этапа это извращения, на которые приходится идти ради совместимости с другими нерабочими великими идеями. в этом плане вызов Dispose в C# или delete в С++ ничем не отличается. разве что в первом случае вы получаете говнообьект, а в С++ вы д-но его диспозите

G>Это ты пытаешься на любом языке писать как на C++.
G>А в реальности не бывает никаких объектов, бывает вызов метода closehandle, который "закрывает" файл. То есть дает доступ другим приложениями в случае эксклюзивного доступа, а также сбрасывает буфер на диск. Если того и другого не треубется в данный момент, то в .NET можно dispose не звать.
что значит не требуется в данных момент? у вас будет расти и расти занятость системы, а вы будете бороться с этим увеличением лимитов вместо того, чтобы искать где там что не дисплозится и переписывать код на using. одна малюсенькакая дотнетовская какашечка чисто теоретически может зажрать сколько угодно памяти и сколько угодно ресурсов. поэтому и приходится писать using

G>Это в C++ важна работа с объектами, ибо она эквивалентна работе с памятью. А в других (нормальных) яызках ты не с объектами работаешь, а с результатом, который нужно получить. Если нужно чтобы после выполнения функции данные гарантированно записались в файл, то ты вызываешь dispose.

G>dispose и delete кстати отличается очень сильно. Но я уж понял, что все что ты пишешь основано на незнании .NET. Ранее ты умудрился using приравнять к auto_ptr
ха-ха-ха как смищьно

G>Чувак, нет никакого destruction в .NET, он только в C++ есть и еще в паре говноязыков, есть только side-эффект, который тебе нужно получить "сейчас", для таких сайд-эффектов часто используется idisposable.

G>Причем если ты привязывает сайд-эффект к деструктору (RAII), то появляется другая проблема, ты не можешь объект передать куда-либо, ибо вызовется конструктор копии, для которого вызовется деструктор, который вызовет эффект раньше времени. Можно, конечно, передать голый указатель , но тогда проблема со временем жизни появляется, можно передать защищенный указатель (ссылку)?
перефразируя поговорку микрософтовскую "ты просто слишком долго пишешь на .NET". обьект создается и уничтожается. всё. больше с ним ничего не может происходить. наличие промежуточных шагов — лисапеды и бесконечное болото для ошибок.

__>>мы хотим контролировать время его жизни. но средствами языка это делать нельзя и мы добавляем велосипед — договариваемся, что код деструктора помещаем в Dispose и вручную будем вызывать его.

G>Мы не хотим время жизни объектов контролировать, это желание C++ника. Мы хотим получить сайд-эффект в точно определенное время. Для этого даже dispose не нужен, просто вызвать метод close или типа того. Но этот метод можно забыть вызвать, а dispose имеет много средств, чтобы избежать таких ситуаций — using, подсказки среды\FxCop.
у нас дело может до close не дойти из-за возникшего по дороге исключения. именно поэтому я и писал про auto_ptr капк гарантия уничтожения обьектов на куче при любом выходе из области видимости, если до тебя еще не дошло

G>Ты наверное все еще не понял, что в 99% случаев если не вызвать dispose, то ничего страшного не случится. Поэтому глупо приравнивать dispose к разрушению объекта. Но я уж понял, что все что ты пишешь основано на незнании .NET

конечно это не разрушение. это лисапед — полуразрушение

G>Чувак, я знаю C++ (и судя по твоему комменту ниже — знаю лучше тебя), это ты не знаешь .NET

а смысл знать .NET ?
он не годится для серверной стороны, так там там линукс везде
он не годится для гуя — так как он сейчас весь вебовский и нужно копать что-то в сторону типизованного жабоскрипта
он не годится для каких-то вычислений из-за корявой модели памяти.

он был просто создан как замена С++ для внутренних проектов Микрософта. Никто другой в здавом уме его использовать не будет С++ый проект внутри MS контролировать невозможно в принципе никаким образом. C# ый — да, он тормозит и еле работает, ну по крайней мере он не так часто падает. Всё остальное уже вторично

__>>а теперь, внимание, обьяснение по поводу auto_ptr — если нас не устраивает стек, хотим на куче, то

__>>void f()
__>>{
__>> x = 10
__>> { <- это типа начало scope using
__>> auto_ptr<ifstream> f = make_unique_ptr() // я уже не помню, тут его как-то инициализируем, открываем
__>> } <- вот тут вот он уничтожится

__>> x = 20

__>>}
G>
G>Убило.
G>Во-первых просто не скомпилируется.
ну ясен пень

G>Во-вторых ты походу не знаешь разницу между auto_ptr и unique_ptr.

G>В-третьих попробуй передать куда-либо auto_ptr.
auto_ptr был создан как раз с целью using — гарантированное уничтожение обьекта при выходе из scope при возникновении исключения. он был создан миллион лет назад и давно уже obsolete.

__>>вот это повредение и пытается симулировать C# со своим Dispose

G>Пойди учебник почитай, не пиши глупостей.
учебник по C#? да я лучше на шиномонтаж работать пойду, чем снова на C# писать
Re: Garbage collection vs manual memory management
От: Васильич  
Дата: 08.01.15 13:27
Оценка: +4 -1
Здравствуйте, johny5, Вы писали:

J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.

J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

Мне кажется, тут налицо попытка идти в чужой монастырь со своим уставом. Фундаментально нет большой разницы между C++ и C#: в последнем случае менеджер памяти умеет автоматически освобождать неиспользуемую более память, но не более того. Очень утрированно можно считать, что "v = null" в C# эквивалентно "delete(v)" в C++, с той разницей, что в последнем случае память будет освобождена немедленно, а в первом — когда-нибудь в будущем.

В обоих случаях программист обязан:
1. Явно закрывать неиспользуемые более ресурсы (файлы, коннекшены к БД, и т.д.)
2. Явно обнулять все дополнительные ссылки на удаляемый объект.

Возьмем ваш пример с кнопкой и прикрепленным к ней звуком. В C++ никто не отменяет обязанность присвоить кнопке новый указатель на звук после рестарта менеджера звуков, соответственно у вас будет некий алгоритм по уведомлению подписанных объектов о рестарте менеджера. Абсолютно то же самое будет в C#. Никаких проблем с зависшими объектами не возникнет.
Re: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:11
Оценка: +3 -1
Здравствуйте, johny5, Вы писали:

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


Меня забавляет твой термин "С++ профессионал". Если ты проффесионал, то наличие конкретных свойств среду для тебя не должно быть ужасом.

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

Ну, а ты просто имеешь однобокий опыт. Расширить свой опыт и вопросы отпадут сами собой. Лично я сделал это более 10 лет назад. Полет нормальный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Garbage collection vs manual memory management
От: Tissot Россия  
Дата: 08.01.15 11:07
Оценка: +3
Здравствуйте, johny5, Вы писали:

J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.


Не могли бы вы расписать, как тут может помочь ручное управление памятью?
Елси вы просто вызовете delete для нужного объекта, те, кто все еще имеет ссылки на него, будут продолжать держать ссылку на уже освобожденный объект, что гораздо хуже.
Re: Просто сначала надо читать, а потом писать...
От: 11molniev  
Дата: 09.01.15 12:02
Оценка: +3
Чувствуется, что вместо того, что бы хотя бы бегло пробежаться глазами по спецификации языка и среды (а она даже на русский переведена...) вы попытались разобраться нахрапом.

J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.

Не-а, главное отличие C++ RAII и C# GC в том, что первый отрабатывает при выходе за пределы видимости, а второй когда захочет. Или вы пишите на C++ в стиле восьмидесятых?
J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.
Ошибочка, не когда угодно, а когда данный объект больше не будет использоваться. В одном случае это определяет программист и может ошибиться и удалить объект к которому ещё будут обращения, во втором среда и может недолго подержать в памяти объект к которому уже не будет обращений. Вот и вся разница — ничё больше.

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.

Все зависит от архитектуры, а не от языка. Если хочется, чтоб и кнопку не трогать и менеджер перезапускать когда приспичит и ресурсы на старый не тратить — то слабосвязанная архитектура с обменом сообщениями. И я для данной задачи в упор не вижу разницы между C# GC / C++ RAII / C void*. Что там, что там надо решать задачу жизни ресурса и во всех случаях подходы одинаковы. Применительно к вашему возмущению в сильно связанной архитектуре: ок, старый менеджер мы выгрузили, пользователь нажал кнопочку и мы радостно поперли по невалидному указателю/хендлу — это очень профессионально .

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.

Я совсем не понимаю, что вы подразумеваете под временем жизни объектов. В GC не надо контролировать время жизни выделенной памяти ибо предполагается, что можно пожертвовать несколькими десятками процентов. Время жизни ресурсов (сокеты, файлы, соединения с БД, ...) надо контролировать всегда и везде, вне зависимости от наличия или отсутствия GC. И отсутствие такого контроля — весьма грубая ошибка.

J>Я сам С++ник и безуспешно пытался пересесть на С#. Я поимел реальных проблем с тем что я впринципе не имею никакого контроля над временем жизни объектов мной созданных. К примеру загрузил я файл в модель, отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств. Всё что тут можно сделать это подчистить везде везде везде ссылки на эту форму, на модель и скрестить пальцы что скоро всё само удалится. И всё равно не срабатывает в 50% случаях.

Я программировал на С++ до изучения С# и никаких проблем с последним не испытал. Время работы с файлом контролируется, хотя бы через using (хм, никакого контроля говорите?). А модель изменяется простым приравниванием. Что там вы имеете в виду под не могу удалить и причем здесь язык не ясно. Ссылки надо подчистить не на форму, а на модель (в С++ вы удаляете объект на который у вас ещё есть ссылки?). Срабатывает в ста случаях корректного использования (десятки лет эксплуатации .Net/Java подтверждают это).

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.

ХЗ. Вся разница, в том, что в языках без GC надо следовать более строгим правилам кодирования, дабы ничего не потерять. А программы с GC жрут памяти больше чем им нужно. Впрочем последнее больше серверная Java, чем .Net.
Re[4]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 17.01.15 05:01
Оценка: +2 -1
Здравствуйте, __kot2, Вы писали:
__>ну вы же сталкивались с тем, что у нас некоторые обьекты держат указатели на системные ресурсы как файлы, хэндлы, потоки. если вы не будете их руками освобождать в dispose у вас приложение будет нестабильно падать по out of resources
И причем тут память?
И зачем хранить в поле класса ссылку на файл?
И в чем проблема если файл закроется не сразу, а после срабатывания ГЦ?
Хоть раз в жизни видел падение от того что хендлы кончались? Я нет, хотя есть подозрение что побольше тебя .Net приложений видел.
В курсе что code analysis в студии показывает все места с незадиспозенным idisposable?

__>в C#-Java вы начинаете писать код в стиле

__>using (...)
__>симулирую auto_ptr. а вот reference couring ptr вам не удастся никаикм образом добиться и придется мучаться технологиями многолетней давности
Курил? Каким образом auto_ptr похож на using?



__>потом вдруг вы столнетесь, что с большими кусками памяти та же история — дефрагментации памяти слишком тяжелая и по уму хорошо бы иметь заранее выделенные буферы или какое-то ручное более низкоуровневое управление памятью — когда большие буферы не перемешаны с мелкими временными обьектами

Это в с++ оно лучше, а с gc долгоживущие и короткоживущие объекты и так вместе не живут буквально после пары сборок мусора.


__>в итоге у вас получится полностью ручной memory management. хрень полнейшая.

Ты представляешь такой класс программистов, который на любом языке может писать как на с++. Я тебя расстрою, описанных тобой проблем просто не существует. Они есть только в с++, а в языках с ГЦ ты в микроскоп не увидишь эти проблемы, даже если тщательно воспроизведешь все условия.
Re[7]: Garbage collection vs manual memory management
От: __kot2  
Дата: 18.01.15 16:12
Оценка: -2 :)
Здравствуйте, gandjustas, Вы писали:
G>Тогда приведи минимальный код, который падает по этой причине. На .NET.
да просто открытие файлов в цикле должно падать
если хотите просимулировать то, о чем я говорю — вставьте в начала частоиспользуемых ф-ий вашего приложение по открытию файла и оно у вас начнет непрдесказуемым способом падать в разных местах по out of resources

G>>>В курсе что code analysis в студии показывает все места с незадиспозенным idisposable?

__>>ну да, показывает лики. и что с ними делать?
G>Вызвать dispose.
понимаете, что вы просто вручную уничтожаете обьект? не бывает никаких init и dispose. бывает создание и уничтожение обьекта. а то, что оно разбито на два этапа это извращения, на которые приходится идти ради совместимости с другими нерабочими великими идеями. в этом плане вызов Dispose в C# или delete в С++ ничем не отличается. разве что в первом случае вы получаете говнообьект, а в С++ вы д-но его диспозите

G>Он нужен для детерминированного освобождения. Так как часто при "закрытии" хендла выполняется много действий Например при закрытии файла сбрасывается буфер на диск, при закрытии сокета — отправка данных из буфера, закрытие соединения с БД — возвращение в пул, чтобы другой поток мог его взять, а не плодить еще одно соединение.

правильно, это должно делаться при разрушении обьекта. разрушение в смысле destruction. мы хотим контролировать время его жизни. но средствами языка это делать нельзя и мы добавляем велосипед — договариваемся, что код деструктора помещаем в Dispose и вручную будем вызывать его.

G>Тем не менее если не использовать idisposable никакой утечки не случится, просто файл\сокет\соединение закроется после сборки мусора. В десктопном приложении никаких проблем от этого не будет вообще.

G>А еще часто используют disposable как некоторый scope Например в razor шаблоне с помощью using указывается где форма начинается и закачивается.
правильно, в С++ это как создавать обьекта на стеке. будет вызыван деструктор при выходе из фрейма. если еще в танке, то можно писать так
void f()
{
x = 10
{ <- это типа начало scope using
ifstream f("filename")
} <- вот тут вот он уничтожится

x = 20
}
а теперь, внимание, обьяснение по поводу auto_ptr — если нас не устраивает стек, хотим на куче, то

void f()
{
x = 10
{ <- это типа начало scope using
auto_ptr<ifstream> f = make_unique_ptr() // я уже не помню, тут его как-то инициализируем, открываем
} <- вот тут вот он уничтожится

x = 20
}

вот это повредение и пытается симулировать C# со своим Dispose
Re[18]: Garbage collection vs manual memory management
От: Константин Россия  
Дата: 19.01.15 19:50
Оценка: +3
Здравствуйте, __kot2, Вы писали:

__>С++ 11 это обычные мелкие доработочки, чтобы каждые свой велосипед не городили посредствами языка, стандартные решения были стандартизованы.

-1

Ни фига себе мелкие доработки:
— move семантика
— возможность по-человечески использовать алгоритмы STL (лямбды)
— нормальный способ итерироваться по коллекциям без ужасов типа BOOST_FOREACH
— std::unique_ptr (нормальных аналогов до выхода C++11 не было)
— избавление от необходимости писать километровые имена типов (auto)
+ по мелочи variadic templates, constexpr, upgrade STL ...

Скажу больше,
— если человек когда-то писал на C++, но не делает это сейчас
— если человек пишет на C++, но не интересуется, не изучал С++11
то он не знает современный C++
Re[10]: Garbage collection vs manual memory management
От: Sinix  
Дата: 18.01.15 19:29
Оценка: 1 (1) :)
Здравствуйте, __kot2, Вы писали:

__>я бы чтобы добиться падения попробовал бы рандомное имя файла давать и еще что-нить читать оттуда, чтобы гарантировать открытие. а то вдруг оно там ленивое? или в оптимизаторе дотнетовском стоит каколй-нить if — типа в цикле если файлы открываем, но не читаем, то не открывать их

nevermind.gif
Re: Garbage collection vs manual memory management
От: Abyx Россия  
Дата: 08.01.15 13:31
Оценка: +2
Здравствуйте, johny5, Вы писали:

J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.


J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


Джавист в чем-то прав. Надо использовать shared_ptr и weak_ptr. У кнопки был бы weak_ptr и она не мешала бы удалить менеджер звуков.

Что касается C# — никто не мешает тебе сделать weak_ptr в C#. Просто там никто так не делает, слишком неудобно/сложно.
In Zen We Trust
Re: Garbage collection vs manual memory management
От: Jack128  
Дата: 08.01.15 13:46
Оценка: +2
Здравствуйте, johny5, Вы писали:

В описанной ситуации в плюсах мы получим битый указатель, а шарпе мемлик, это понятно.
Меня вот какой вопрос больше интересует. В плюсах при использовании какого нить отладочного манагера памяти при нажатии на кнопку, ссылающуюся на убитый менеджер звуков, мы практически гарантированно AV получим и начнем править багу. А вот в .NET обработчик нормально отработает, ошибка будет логическая и возможно плохо заметная. Как с этим бороться ?
Re[3]: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 14:46
Оценка: +1 :)
Здравствуйте, 0BD11A0D, Вы писали:

BDA>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»). Распространять ужостики про другие языки — характерная часть этой профессии, потому, что язык очень часто используется неоправдано, и если этого не делать — их поувольняют и заменят более дешевыми.


Согласен со всем кроме более дешевых. Хороший специалист дешево не стоит. Я замечал за сиплюсплюсниками эдакое завышенное самомнение, что мол на других языках пишут те кто с плюсами не справляется. Это не более чем раздутое ЧСВ.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Garbage collection vs manual memory management
От: Кодт Россия  
Дата: 09.01.15 16:26
Оценка: +2
Здравствуйте, johny5, Вы писали:

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


Ужос состоит в том, что и плюсовики, и менеджедчики в равной степени обольщаются и переупрощают видение ситуации.
Надо взять перфоратор, алмазное долото и бетонный блок. И выдолбить большими буквами:
НЕ СВАЛИВАЙТЕ В ОДНУ КУЧУ УПРАВЛЕНИЕ ПАМЯТЬЮ И ДРУГИЕ ВОПРОСЫ ВЛАДЕНИЯ.

В плюсах, например, типичнейшая грабля — это управление жизнью взаимозависимых синглетонов.
Можно изобретать всякие хитроумные политики, как это ещё Александреску показал в 2004 году, но, в конце концов, это сведётся не более чем к автоматизации и уменьшению синтаксического шума вокруг продуманной, проговоренной и написанной на бумажке стратегии: как чего поднимать и как чего убивать.

Если у программы есть такой юз-кейс "перезагрузить менеджер звуков", то пусть лучше это будет явная функция с явным вызовом всех соответствующих недр. А не "let them crash".
Безотносительно того, на shared_ptr всё это добро сделано или на delete.
Пусть у менеджера будет метод "самозачиститься", который выполняет то же, что и деструктор, но без окончательного самоубийства.
И пусть пользователи менеджера могут убедиться, что он полудохлый, и не упасть при этом, а переключиться на актуальный экземпляр менеджера.

Уж на то пошло, это делается на двойной косвенности.
class SoundManager // всё, что вы хотели иметь от этого менеджера
{
public:
  SoundManager(.....); // код загрузки здесь
  ~SoundManager(); // код выгрузки здесь (в т.ч. через деструкторы членов-данных и баз)
  .....
};

class SoundManagerHolder
{
  unique_ptr<SoundManager> man_;
  void load()     { man_ = make_unique<SoundManager>(.....); }
  void lazyload() { if(!man_) load(); }
  void unload()   { man_.reset(); }
public:
  explicit SoundManagerHolder(bool start) { if(start) load(); }
  SoundManager& get() const
  {
    lazyload();
    return *man_;
  }
  void reset(bool restart)
  {
    unload();
    if(restart) load();
  }
};
typedef shared_ptr<SoundManagerHolder> SoundManagerPointer; // распоряжайтесь.
Перекуём баги на фичи!
Re: Garbage collection vs manual memory management
От: Nuseraro Россия  
Дата: 11.01.15 20:50
Оценка: +1 :)
А сама компиляция в машинные коды? Вы видели, что получается? Это вообще какой-то мракобесный оверхед!

Невозможность контролировать результирующий машинный код — неприемлемо для меня, поэтому пишу только на кошерном асме.
Homo Guglens
Re[15]: Garbage collection vs manual memory management
От: __kot2  
Дата: 19.01.15 01:37
Оценка: -2
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, __kot2, Вы писали:
__>>Здравствуйте, gandjustas, Вы писали:
G>>>Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
__>>это как в Советском Союзе? Сначала создать проблему, а потом героически ее преодолевать?
G>Ты не в курсе, что .net был создан сильно до того, как появились все эти платформы?
а С++ когда был создан?
есть очень простой критерий удачности решений/технологий
хорошие решения имеют приятные неожиданные побочные эффекты
плохие решения имеют неприятные неожиданные побочные эффекты

это самый лучший в мире и 100% рабочий критерий грамотности какой-то разработки — попробовать применить ее в области для которой она не создавалась.
Re[16]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.15 08:29
Оценка: -1 :)
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, gandjustas, Вы писали:

G>>Здравствуйте, __kot2, Вы писали:
__>>>Здравствуйте, gandjustas, Вы писали:
G>>>>Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
__>>>это как в Советском Союзе? Сначала создать проблему, а потом героически ее преодолевать?
G>>Ты не в курсе, что .net был создан сильно до того, как появились все эти платформы?
__>а С++ когда был создан?
В 2011 году, все предыдущие версии безнадежно больны и практически неизлечимы (неприятные побочные эффекты, ага).

Но и это не играет никакой роли, ибо никакого универсального фреймворка, работающего более чем на одной платформе в принципе нет для C++.
Про Qt даже не вспоминай, выглядит как говно, в приличном обществе сразу по лицу за такое бьют.

В итоге вместо универсальности ты получишь N разных codebase для N разных платформ. Желаю удачи в поддержке.
Re[10]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.15 19:45
Оценка: -2
Здравствуйте, Константин, Вы писали:

К>Здравствуйте, gandjustas, Вы писали:


G>>Причем если ты привязывает сайд-эффект к деструктору (RAII), то появляется другая проблема, ты не можешь объект передать куда-либо, ибо вызовется конструктор копии, для которого вызовется деструктор, который вызовет эффект раньше времени. Можно, конечно, передать голый указатель , но тогда проблема со временем жизни появляется, можно передать защищенный указатель (ссылку)?


К>Эта рассуждение устарело после выхода C++11. Move-only типы решают вопрос передачи владения.


Это тоже костыль для небезопасных указателй и автоматических деструкторов.
Re[5]: Пара примеров
От: andyag  
Дата: 10.01.15 07:26
Оценка: 8 (1)
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, andyag, Вы писали:


J>>>В С++ эта модульность — спасительный круг в мире висящих указателей, определённый функционал просто не будет запущен если какое то условие на более высоком уровне не было выдержано. В данном случае какой то блок внутри Модуля 1 будет просто отключен и что какие ссылки и структуры он содержит и куда оно всё ссылается оно всё становится неважно. По сути это приводит к повышению требования к качеству ООП в С++.


A>>Не очень понятно. Обычно отключение куска кода — это в простейшем случае if вокруг какого-то флажка. Этим флажком кто-то должен управлять. В вашей иллюстрации, скорее всего, тот самый компонент, который "кто-то, кто явно убивает модуль 2". Убийство объекта это не delete, и не вызов сборщика мусора. Это в первую очередь заявление "этот объект теперь неактуален".


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


Вы как-то очень размыто используете термин "жив". В простейшем случае будет как-то вот так:
class SoundManager {
  void playSound() {...}
}

class SoundPlayer {
  SoundManager soundManager = null;

  public void playSound() {
    if(soundManager == null) { // тот самый if с флажком
      throw new RuntimeException("There's no sound manager");
    }

    soundManager.playSound();
  }

  public void setSoundManager(SoundManager soundManager) {
    this.soundManager = soundManager;
  }
}

...

SoundPlayer player = new SoundPlayer();

player.playSound(); // throws

player.setSoundManager(new SoundManager("sound manager one"));
player.playSound(); // works

player.setSoundManager(null);
player.playSound(); // throws

Если вы имеете в виду ситуацию, когда существующий SoundManager по какой-то причине становится невалидным, это уже не настолько тривиальный кейз. Можно сделать например вот так:
interface IDisconnectable {
  void setOnDisconnectedListener(OnDisconnectedListener listener);
}

class SoundManager implements IDisconnectable {
  ...
}

class SoundPlayer implements OnDisconnectedListener {
  void setSoundManager(SoundManager soundManager) {
    if(this.soundManager != null) {
      this.soundManager.setOnDisconnectedListener(null);
    }

    this.soundManager = soundManager;
    soundManager.setOnDisconnectedListener(this);
  }

  void onDisconnected(SoundManager sender) {
    sender.setOnDisconnectedListener(null);
    this.soundManager = null;
  }

  public void playSound() {
    if(soundManager == null) { // и снова - тот самый if с флажком
      throw new RuntimeException("There's no sound manager");
    }

    soundManager.playSound();
  }
}

Если не хочется так накручивать SoundPlayer, можно сделать SoundManagerHolder extends SoundManager, который будет хранить ссылку на настоящий SoundManager до тех пор, пока тот SoundManager не скажет, что он поломался. Пока не поломался — все вызовы будет делегировать настоящему объекту (если есть) или кидать исключения (если нет).
Re: Garbage collection vs manual memory management
От: c-smile Канада http://terrainformatica.com
Дата: 08.01.15 22:14
Оценка: 4 (1)
Здравствуйте, johny5, Вы писали:

На самом деле проблема конечно есть.

UI код характризуется достаточно сложными ownership graphs когда сложно установить кто чем владеет.
То же самое про асинхронный код где promise promise'ом погоняет.

Т.е. GC в UI скорее благо чем зло.

Идеальная среда/язык это нечто позволяющее декларирвать domains — вот manageable (GCable) domain/namespace, а вот deterministic domain.

Я был питал надежды на D language в этом смысле. Там в принципе можно руками писать delete когда нужно.
Но это к сожалению не отменяет глобальный и весьма консервативный GC.

В результате пришел к Sciter в котором code behind UI пишется на JavaScript alike языке с четко очерченным managed <-> native gateway.
То что называется business logic удобно, эффективно и детерминировано пишется на C/C++. UI же декларатинвный и managed.
Это в принципе близко, но не 100% идеально конечно.

Что-то типа @autoreleasepool {} areas из ObjC, но не так прямолинейно...

А воообще тема интересная. Вангую что языкостроение будет развиваться в эту сторону тоже в боижайшее время.
Re: Garbage collection vs manual memory management
От: andyag  
Дата: 09.01.15 06:57
Оценка: 4 (1)
Здравствуйте, johny5, Вы писали:

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


Достаточно просто ввести посредника между кнопкой и менеджером звуков:
1. Продолжительность жизни посредника должна быть как минимум такой же, как продолжительность жизни кнопки
2. Посредник должен знать о существовании менеджера звуков
3. "Внешняя логика", которая перезапускает менеджер звуков, должна передавать посреднику ссылку на новый объект менеджера
Вот пример:
class SoundManager {...} // эту штуку вы хотите убивать и делать новую

class SoundService : IListenToSoundManagerUpdates 
{
  private SoundManager _soundManager;

  public void OnSoundManagerHasChanged(SoundManager sm)
  {
    _soundManager = sm;
  }

  public void PlaySound()
  {
    _soundManager.PlaySound();
  }
}

winAmpButton.Click += {
  _soundService.PlaySound();
};

restartSoundManagerButton.Click += {
  var soundManager = new SoundManager("another sound library");
  _soundService.OnSoundManagerHasChanged(soundManager);
};

Я не вижу чем принципиально будет отличаться решение на C++. В мире C#/Java можно ещё IoC-контейнер под это дело прикрутить, и "виртуализировать" SoundManager: снаружи он останется как есть, но внутри него будет SoundService со всеми вытекающими.

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


Нужно контролировать не "физическую" жизнь объектов, а "логическую" — они не всегда совпадают. Вы описали задачу именно с точки зрения логической части, но свели проблему — к физической. С точки зрения "логической" части C#/Java легко дадут фору C++ хотя бы засчёт IoC-контейнеров.

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Вы бы показали как вы это на C++ делаете, можно было бы более предметно сравнить.
Re: Garbage collection vs manual memory management
От: s_aa Россия  
Дата: 08.01.15 10:27
Оценка: +1
>отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств.

Ну и загружай новую, старая подчистится GC если ссылок нет, зачем удалять, забыл про нее и все.
Жизнь не обязана доставлять удовольствие. Достаточно отсутствия страданий.
Re: Garbage collection vs manual memory management
От: AlexRK  
Дата: 08.01.15 13:19
Оценка: +1
Здравствуйте, johny5, Вы писали:

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Ну так в C/С++ вы получите крах программы (в лучшем случае), если насильственно удалите то, что где-то используется.

Мне больше всего нравится подход Rust — ни сборки мусора, ни опасного удаления вручную.
Re[4]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 08.01.15 20:36
Оценка: :)
Здравствуйте, Sergey J. A., Вы писали:

J>>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.


J>>Я об этом и говорю что тут токо сиди и надейся что оно сработает, нет в языке средств прямого управления временем жизни объекта.


SJA>А в плюсах что будет? Указатель на мусор?


Как то не возникает с этим проблемы в C++, не все мусорные указатели на самом деле используются. Кроме того, в С++ есть возможность передаваемую структуру данных скопировать by value. В С# это не подрузамевается но если сильно надо то конечно можно, только какой смысл тогда кодить на C# если там так всё сложно и ты должен думать над передачей каждого указателя и каждой лямбдой. Ничего GC тогда не облегчает а даже наоборот. Кроме того мемори лики оочень сложно искать, я потратил неделю. В случае с С++ висячий указатель выстрелил бы почти сразу.
Re: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:25
Оценка: +1
Здравствуйте, johny5, Вы писали:

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Это типичные плюсове предрассудки.

Память просто никто не выгружает. Сменил указатель на новое значение и все. Забыл про то что там было старое. Все выгружается автоматом. Нет ссылок, нет объекта.

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

Общие советы просы:
1. Не использовать статических переменных кроме как для организации неких сервисов доступных только для чтения.
2. Локализовывать работу с большими графами в отдельных функциях. Скажем у нас есть функция Parse() которая создает огромный граф объектов да еще и не один. Но по ее завершении ссылка на этот граф должна быть одна. И именно она возвращается из этой функции. Если не положить ее в статическую переменную, то рано или поздно она сдохнет.
3. Стараться локализовывать работу с неуправляемыми ресурсами в отдельных функциях. Прочел данные, переложил их в объекты и дальше работаешь с управляемыми объктоами.
4. Если специфика работы требует иметь некоторые догоживущие подключения (типа соеденения с БД), то использовать паттерн "Пул" выделяя холдеры ресурсов живщие только на время кратковременной обработки. Такой холдер засовывается в using и автоматически освобождается при выходе за пределы using-а. Он берет реальное подключение из пула и возвращает его обратно в своем Dispose().
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Garbage collection vs manual memory management
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 09.01.15 05:54
Оценка: +1
Здравствуйте, hi_octane, Вы писали:

_>Нужен механизм который бы гарантировал что после delete состояние программы полностью определено и синтаксис для описания того, что именно считать состоянием и как его определить. Как только такое чудо света кто-то придумает, так сразу и GC будет не нужен, и, внезапно, delete тоже будет не нужен. Ведь из описания такого контракта компилятору будет ясно что уже можно удалять, а что ещё нет.


ATS же. Там все это было еще сто лет назад. Но на практике шибко сложно в использовании, дальше полутора академиков не пошло.
Re[4]: Garbage collection vs manual memory management
От: 0BD11A0D  
Дата: 09.01.15 18:50
Оценка: :)
Здравствуйте, VladD2, Вы писали:

BDA>>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»). Распространять ужостики про другие языки — характерная часть этой профессии, потому, что язык очень часто используется неоправдано, и если этого не делать — их поувольняют и заменят более дешевыми.


VD>Согласен со всем кроме более дешевых. Хороший специалист дешево не стоит.


Во-первых, хороший специалист для кого? Для себя он хорош, или для работодателя? У них разные интересы (иногда диаметрально). По моим субъективным ощущениям, примерно в 75% случаев хороший программист, независимо от языка, должен сказать: «Тут программист не нужен» и уйти в закат. Без денег. Показывала тут знакомая проект, над которым работает — веб-аппы для маркетологов. У маркетологов у всех есть законный Excel. Вместо того, чтобы сделать за полчаса выгрузку в XML, пилят «онлайн-аналитику». Я говорю, зачем этим мудакам онлайн? Они в метро на смартфоне работают? На айпадике? Или в офисе на стуле за компьютером с Excel'ем? То, что вы тут собрали, это же корявее всякого допотопного офиса-шмофиса. Как только что-нибудь изменится, опять вас звать. Она говорит, наверное, пользоваться не умеют, да и что за печаль? Главное, платят. Это еще вам случай, когда работодатель действовал заодно с хорошим специалистом, напарив заказчика. Потом специалист начинает напаривать самого работодателя, типа, тут не обойтись без того, сего и этого. Ох, щас прочитают профессионалы этот мой анонимный донос, и дадут просраться! Стоит ли удовольствие от беседы последующего потока гавна — сам не знаю. Нет, наверное, просто не фейсбучиться же для расслабона.

Ладно, едем дальше. Во-вторых, даже если они будут получать одинаковую зарплату, человек, неоправданно протащивший плюсы, обойдется среднестатистически дороже. У него больше возможностей запутать код (а раз он протащил ненужный язык, можно ли надеяться, что он не протащит и ненужный код?). Он тупо дольше будет управлять памятью и отлаживаться. Больше ошибок будет в релизе и бороться с ними сложнее. Заменить такого труднее. Все это деньги.

В-третьих, не будут они получать одинаковую зарплату. Разнорабочий плюсовик получает больше разнорабочего шарпея. Достаточно посмотреть объявления от одного и того же нанимателя.

В-четвертых, я не говорил, что кто-то дешевый, а кто-то дорогой. Я сказал — ДЕШЕВЛЕ. Посмотрите объявления — до 110 шарп, до 120 плюсы. До 60 P (пэ), до 90 плюсы. Если бы плюсовикам нечего было защищать, они бы так себя не вели.

В-пятых, как ни крути, управлять памятью требует больших знаний, а плюсы сложнее. И бывает, что без них не обойтись. Я всего лишь говорил о том, что суют их куда ни попадя. С подачи паразита в собственном теле — ИТ-директора какого-нибудь. Который хочет больше бюджетов, а не меньше, представьте себе.

Извините, тут про программирование, да про философию, а я все про жизнь. Впредь все обязуюсь и больше не.
Re[2]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.01.15 15:45
Оценка: +1
Здравствуйте, chaotic-good, Вы писали:

CG>2) если объект долгоживущий, желательно чтобы он был неизменяемым, если ты создал крупный граф объектов, который пережил множество сборок мусора и попал в самое долгоживущее поколение, изменение объектов в нем будет приводить к полной пересборке мусора. Это противоположенно тому, что обычно делают в плюсах/Си — там лучше создавать удалять объекты пореже, чтобы не тратить время в аллокаторе. Вот например пулл объектов в GC языке будет плохо работать, обекты в пулле живут долго но инициализируются периодически заново нагружая GC, в GC языке лучше не использовать пуллы объектов а просто создавать объекты когда нужно в куче и не заморачиваться, это банально быстрее.


На практике это не так.
Основные тормоза создаются при генерации мусора. Меньше мусора == реже сборки == выше производительность даже при более дорогих сборках мусора.
Пулы объектов в языках с GC работают прекрасно.
Re[3]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.01.15 15:53
Оценка: +1
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, Кодт, Вы писали:


К>>НЕ СВАЛИВАЙТЕ В ОДНУ КУЧУ УПРАВЛЕНИЕ ПАМЯТЬЮ И ДРУГИЕ ВОПРОСЫ ВЛАДЕНИЯ.


_NN>С этим абсолютно согласен.

_NN>Сборщик мусора решает проблему утечки памяти но никак не проблему утечек ресурсов.

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

GC исправляет этот класс ошибок, но может привести к "утечкам" из-за хранения ссылок на объекты, которые уже не используются.
И снова нужно следовать стратегии управления владением, чтобы таких ошибок избежать.

Исходный вопрос касался как раз владения и имеет отдаленное отношение к управлению памятью.
Re[4]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.01.15 21:38
Оценка: +1
Здравствуйте, chaotic-good, Вы писали:

G>>На практике это не так.

G>>Основные тормоза создаются при генерации мусора. Меньше мусора == реже сборки == выше производительность даже при более дорогих сборках мусора.

CG>И при этом лучше, когда мусор короткоживущий. Ну и не только мусор, нужно в целом о структурах данных думать с позиции GC (в том числе), стараться делать из более gc-friendly, чтобы создавать меньше работы для сборщика мусора, pointer chasing в стиле С/С++ тут до добра не доведет.

Меньше мусора лучше чем короткоживущий мусор.

G>>Пулы объектов в языках с GC работают прекрасно.


CG>У меня был случай, когда я на практике наблюдал обратное — после выпиливания пулла и замены его на обычный new, все стало работать быстрее и приложение стало проводить меньше времени за сборкой мусора. В принципе, это становится очевидно и если просто почитать про устройство gc в .net, в msdn есть очень хорошая статья на эту тему, ты должно быть ее читал. Пулл объектов может работать хорошо, если ссылки внутри этих объектов не меняются, только данные, соответственно не дергается сборка в gen 2, но в общем случае, пуллы рекомендовать нельзя, особенно для короткоживущих объектов.


Любой код можно написать плохо. Можно считать это аксиомой. Но даже тысячи плохо написанных пулов объектов не делают пулинг с gc неэффективным.
Если посмотреть внтуренности .NET и Roslyn, то можно заметить, что очень часто используется thread-local пул объектов StringBuilder, который очень даже изменяемый. На Channel9 даже есть запись с teched где объясняют почему так.

Но тут есть особенность. По умолчанию хорошо работает пул размером 1. Я проводил замеры с пулами больших размеров — они зачастую приводят к падению производительности.

Bpexfnm jnc.lf — http://codeblog.jonskeet.uk/2014/08/01/object-pooling-and-thread-safety/ и далее по ссылкам.
Re[3]: Garbage collection vs manual memory management
От: __kot2  
Дата: 17.01.15 00:42
Оценка: -1
Здравствуйте, mrTwister, Вы писали:
T>Здравствуйте, __kot2, Вы писали:
__>>да, есть такой прикол — вместо delete приходится вызывать dispose. поэтому грамотная работа с памятью в C#, Java становится ничем не проще С++
T>Интересно, какое отношение Dispose имеет к работе с памятью?
ну вы же сталкивались с тем, что у нас некоторые обьекты держат указатели на системные ресурсы как файлы, хэндлы, потоки. если вы не будете их руками освобождать в dispose у вас приложение будет нестабильно падать по out of resources

в случае с reference counting такой проблемы нет — как только обьект вам не нужен, ресурс будет высвобожден

в C#-Java вы начинаете писать код в стиле
using (...)
симулирую auto_ptr. а вот reference couring ptr вам не удастся никаикм образом добиться и придется мучаться технологиями многолетней давности

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

в итоге у вас получится полностью ручной memory management. хрень полнейшая.
Re[5]: Garbage collection vs manual memory management
От: __kot2  
Дата: 17.01.15 18:19
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, __kot2, Вы писали:

__>>ну вы же сталкивались с тем, что у нас некоторые обьекты держат указатели на системные ресурсы как файлы, хэндлы, потоки. если вы не будете их руками освобождать в dispose у вас приложение будет нестабильно падать по out of resources
G>И причем тут память?
G>И зачем хранить в поле класса ссылку на файл?
G>И в чем проблема если файл закроется не сразу, а после срабатывания ГЦ?
G>Хоть раз в жизни видел падение от того что хендлы кончались? Я нет, хотя есть подозрение что побольше тебя .Net приложений видел.
да, конечно, много раз

G>В курсе что code analysis в студии показывает все места с незадиспозенным idisposable?

ну да, показывает лики. и что с ними делать?

__>>в C#-Java вы начинаете писать код в стиле

__>>using (...)
__>>симулирую auto_ptr. а вот reference couring ptr вам не удастся никаикм образом добиться и придется мучаться технологиями многолетней давности
G>Курил? Каким образом auto_ptr похож на using?
ну, это не мой ник похож на "ганджубас". а зачем по-вашему вообще нужен using если в C# все так хорошо с захватом и освобождением ресурсов системы?
Отредактировано 17.01.2015 18:50 __kot2 . Предыдущая версия .
Re[6]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 17.01.15 23:06
Оценка: -1
Здравствуйте, __kot2, Вы писали:

__>ну, это не мой ник похож на "ганджубас". а зачем по-вашему вообще нужен using если в C# все так хорошо с захватом и освобождением ресурсов системы?


Не стоит в это втягиваться. Просто поставь ему минус за хамство и всё.
Re[8]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.01.15 18:06
Оценка: +1
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, gandjustas, Вы писали:

G>>Тогда приведи минимальный код, который падает по этой причине. На .NET.
__>да просто открытие файлов в цикле должно падать
Проверь
static void Main(string[] args)
{
    for (int i = 0; i < 1000000; i++)
    {
        new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
    }
}

Не падает

__>если хотите просимулировать то, о чем я говорю — вставьте в начала частоиспользуемых ф-ий вашего приложение по открытию файла и оно у вас начнет непрдесказуемым способом падать в разных местах по out of resources

Не будет.

Ты только что расписался, что не знаешь как работает GC и .NET вообще.

G>>>>В курсе что code analysis в студии показывает все места с незадиспозенным idisposable?

__>>>ну да, показывает лики. и что с ними делать?
G>>Вызвать dispose.
__>понимаете, что вы просто вручную уничтожаете обьект? не бывает никаких init и dispose. бывает создание и уничтожение обьекта. а то, что оно разбито на два этапа это извращения, на которые приходится идти ради совместимости с другими нерабочими великими идеями. в этом плане вызов Dispose в C# или delete в С++ ничем не отличается. разве что в первом случае вы получаете говнообьект, а в С++ вы д-но его диспозите
Это ты пытаешься на любом языке писать как на C++.
А в реальности не бывает никаких объектов, бывает вызов метода closehandle, который "закрывает" файл. То есть дает доступ другим приложениями в случае эксклюзивного доступа, а также сбрасывает буфер на диск. Если того и другого не треубется в данный момент, то в .NET можно dispose не звать.

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

dispose и delete кстати отличается очень сильно. Но я уж понял, что все что ты пишешь основано на незнании .NET. Ранее ты умудрился using приравнять к auto_ptr


G>>Он нужен для детерминированного освобождения. Так как часто при "закрытии" хендла выполняется много действий Например при закрытии файла сбрасывается буфер на диск, при закрытии сокета — отправка данных из буфера, закрытие соединения с БД — возвращение в пул, чтобы другой поток мог его взять, а не плодить еще одно соединение.

__>правильно, это должно делаться при разрушении обьекта.

Ага, см выше про разрушение объекта.

__>разрушение в смысле destruction.

Чувак, нет никакого destruction в .NET, он только в C++ есть и еще в паре говноязыков, есть только side-эффект, который тебе нужно получить "сейчас", для таких сайд-эффектов часто используется idisposable.
Причем если ты привязывает сайд-эффект к деструктору (RAII), то появляется другая проблема, ты не можешь объект передать куда-либо, ибо вызовется конструктор копии, для которого вызовется деструктор, который вызовет эффект раньше времени. Можно, конечно, передать голый указатель , но тогда проблема со временем жизни появляется, можно передать защищенный указатель (ссылку)?

__>мы хотим контролировать время его жизни. но средствами языка это делать нельзя и мы добавляем велосипед — договариваемся, что код деструктора помещаем в Dispose и вручную будем вызывать его.

Мы не хотим время жизни объектов контролировать, это желание C++ника. Мы хотим получить сайд-эффект в точно определенное время. Для этого даже dispose не нужен, просто вызвать метод close или типа того. Но этот метод можно забыть вызвать, а dispose имеет много средств, чтобы избежать таких ситуаций — using, подсказки среды\FxCop.

Ты наверное все еще не понял, что в 99% случаев если не вызвать dispose, то ничего страшного не случится. Поэтому глупо приравнивать dispose к разрушению объекта. Но я уж понял, что все что ты пишешь основано на незнании .NET

G>>Тем не менее если не использовать idisposable никакой утечки не случится, просто файл\сокет\соединение закроется после сборки мусора. В десктопном приложении никаких проблем от этого не будет вообще.

G>>А еще часто используют disposable как некоторый scope Например в razor шаблоне с помощью using указывается где форма начинается и закачивается.
__>правильно, в С++ это как создавать обьекта на стеке. будет вызыван деструктор при выходе из фрейма. если еще в танке, то можно писать так
__>void f()
__>{
__> x = 10
__> { <- это типа начало scope using
__> ifstream f("filename")
__> } <- вот тут вот он уничтожится

__> x = 20

__>}
Чувак, я знаю C++ (и судя по твоему комменту ниже — знаю лучше тебя), это ты не знаешь .NET

__>а теперь, внимание, обьяснение по поводу auto_ptr — если нас не устраивает стек, хотим на куче, то

__>void f()
__>{
__> x = 10
__> { <- это типа начало scope using
__> auto_ptr<ifstream> f = make_unique_ptr() // я уже не помню, тут его как-то инициализируем, открываем
__> } <- вот тут вот он уничтожится

__> x = 20

__>}

Убило.
Во-первых просто не скомпилируется.
Во-вторых ты походу не знаешь разницу между auto_ptr и unique_ptr.
В-третьих попробуй передать куда-либо auto_ptr.
В-четвертых ты вообще не понимаешь как работает .NET вообще и IDisposable в частности.

__>вот это повредение и пытается симулировать C# со своим Dispose

Пойди учебник почитай, не пиши глупостей.
Re[10]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.01.15 21:10
Оценка: +1
Здравствуйте, __kot2, Вы писали:

__>>>да просто открытие файлов в цикле должно падать

G>>Проверь
G>>
G>>static void Main(string[] args)
G>>{
G>>    for (int i = 0; i < 1000000; i++)
G>>    {
G>>        new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
G>>    }
G>>}
G>>

G>>Не падает
__>ну, в общем-то интересная задачка наверное. я бы чтобы добиться падения попробовал бы рандомное имя файла давать и еще что-нить читать оттуда, чтобы гарантировать открытие. а то вдруг оно там ленивое? или в оптимизаторе дотнетовском стоит каколй-нить if — типа в цикле если файлы открываем, но не читаем, то не открывать их

Ага, магия прям.

Но ты не стесняйся, глянь исходники http://referencesource.microsoft.com/mscorlib/system/io/filestream.cs.html
Никакой магии, честно зовется Win32Native.SafeCreateFile, который по сути CreateFile из WinAPI
Естественно оптимизатор ничего не знает о то, что такое FileStream, да и запускал под дебагом.



__>>>если хотите просимулировать то, о чем я говорю — вставьте в начала частоиспользуемых ф-ий вашего приложение по открытию файла и оно у вас начнет непрдесказуемым способом падать в разных местах по out of resources

G>>Не будет.
__>я сам сталкивался недавно с этим. создаешь просто пару сотен потоков и начинаешь в них что-то делать. у тебя то там, то там out of resources
Да ладно?
        static void Main(string[] args)
        {
            for (int i = 0; i < 300; i++)
            {
                new Thread(() =>
                {
                    for (int j = 0; j < 1000000; j++)
                    {
                        new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                    }
                }).Start();
            }
        }

Не падает.

Готов спорить что ты сталкивался с тем, что у тебя кривые руки и ты не знаешь .NET.

G>>Ты только что расписался, что не знаешь как работает GC и .NET вообще.

__>а он что, может отловить когда handle закончились? он смотрит на оставшуюся память. откуда он знает, что у нас еще и лимит по хэндлам или там, потокам?
А зачем ему это знать? Сборшик мусора срабатывает на 256к памяти, старые хендлы в этот момент закроются. Лимит в винде около миллиона, посчитаешь сам почему ГЦ не должен знать сколько там лимит?

__>раньше был лимит по файловым хэндлам вроде около 5000 сейчас по-моему его тысяч до 100 увеличили как раз по причине что падает вся Явовское-дотнетовское. ну да, решение в духе этих языков. есть же другие лимиты — на потоки, на графические примитивы, на, там, кто его знает что еще. не только в обьеме памяти дело.

16 тысяч был еще до w95, и то только потому что внтури хранилось в духбайтном слове, а хендл был кратным 4. Начиная с W2000 стало двойное слово и убрали кратность 4, стало 2М хнедлов. Так практически везде — потоки, сокеты итп. В последних версиях МСДН даже убрали эти значения, ибо практически их достичь невозможно, память раньше кончится. (если не в курсе, то за каждым хендлом стоит структура в ядре, которая занимает сильно больше 4 байт).

Но это не имеет никакого значения, так как .NET не допускает утечек и надо что-то специально делать, чтобы лимитов достичь.
Это в C++ является проблемой, а в .NET — нет.


__>>>понимаете, что вы просто вручную уничтожаете обьект? не бывает никаких init и dispose. бывает создание и уничтожение обьекта. а то, что оно разбито на два этапа это извращения, на которые приходится идти ради совместимости с другими нерабочими великими идеями. в этом плане вызов Dispose в C# или delete в С++ ничем не отличается. разве что в первом случае вы получаете говнообьект, а в С++ вы д-но его диспозите

G>>Это ты пытаешься на любом языке писать как на C++.
G>>А в реальности не бывает никаких объектов, бывает вызов метода closehandle, который "закрывает" файл. То есть дает доступ другим приложениями в случае эксклюзивного доступа, а также сбрасывает буфер на диск. Если того и другого не треубется в данный момент, то в .NET можно dispose не звать.
__>что значит не требуется в данных момент? у вас будет расти и расти занятость системы, а вы будете бороться с этим увеличением лимитов вместо того, чтобы искать где там что не дисплозится и переписывать код на using.
С чего это "занятость системы" будет расти? Если нет ссылок на объект, то за один проход GC он удалится, и ничего расти не будет. Сборка мусора в поколении 0 выполняется порядка 100 раз в секунду, так что ты даже не увидишь чтобы что-то росло. Ты походу вообще не понимаешь как работает ОС и .NET.


__>одна малюсенькакая дотнетовская какашечка чисто теоретически может зажрать сколько угодно памяти и сколько угодно ресурсов. поэтому и приходится писать using

Ну ты уже расписался в непонимании, можешь не продолжать. Я тебе пример кода без using привел, запусти и посмотри как он расходует ресурсы.
Ты до сих пор не понимаешь, что даже если не писать using никаких утечек не будет.


G>>Это в C++ важна работа с объектами, ибо она эквивалентна работе с памятью. А в других (нормальных) яызках ты не с объектами работаешь, а с результатом, который нужно получить. Если нужно чтобы после выполнения функции данные гарантированно записались в файл, то ты вызываешь dispose.

G>>dispose и delete кстати отличается очень сильно. Но я уж понял, что все что ты пишешь основано на незнании .NET. Ранее ты умудрился using приравнять к auto_ptr
__>ха-ха-ха как смищьно
Тебе смешно, что ты не знаешь что такое auto_ptr и using?

__>перефразируя поговорку микрософтовскую "ты просто слишком долго пишешь на .NET". обьект создается и уничтожается. всё. больше с ним ничего не может происходить. наличие промежуточных шагов — лисапеды и бесконечное болото для ошибок.

Какой объект? CloseHandle надо вызвать. Это в C++ модно (потому что более безопасно чем любой другой подход) всеподряд привязывать к уничтожению объекта. Но это не значит, что в любом языке так стоит делать. Ты же ничего кроме C++ не знаешь (да и его плохо судя по всему), поэтому и пишешь фигню. Бросай, лучше учебники читай.


__>у нас дело может до close не дойти из-за возникшего по дороге исключения.

Ну да, не придумали try\finally конструкцию в C++, поэтому все в деструкторах. В других языка есть другие средства (к счастью).

__>именно поэтому я и писал про auto_ptr капк гарантия уничтожения обьектов на куче при любом выходе из области видимости, если до тебя еще не дошло

Да и до сих пор не дошло что ты хочешь сказать...
Что using дает гарантию уничтожения объекта при выходе из области? Так не дает, можно за пределами using обратиться к объекту, IDisposable это не уничтожение объекта.
Ты какую то фигню сморозил, тем более ты не знаешь как работает auto_ptr, я же говорю попробуй его в метод передать.


G>>Ты наверное все еще не понял, что в 99% случаев если не вызвать dispose, то ничего страшного не случится. Поэтому глупо приравнивать dispose к разрушению объекта. Но я уж понял, что все что ты пишешь основано на незнании .NET

__>конечно это не разрушение. это лисапед — полуразрушение
Что значит "полуразрушение" ? Ты о чем вообще? Лисапед для чего?

G>>Чувак, я знаю C++ (и судя по твоему комменту ниже — знаю лучше тебя), это ты не знаешь .NET

__>а смысл знать .NET ?
Чтобы моз работал, а не раскисал.

Кстати а зачем тебе знать C++?


__>он не годится для серверной стороны, так там там линукс везде

Странно, более 10 лет пишу исключительно серверные приложения на .NET. Так что "везде" это только в твоем воображаемом мире. Вот например этот форум вовсе не на линуксе.
Там где не .NET, там Java, а C++ днем с огнем не сыщешь.

__>он не годится для гуя — так как он сейчас весь вебовский и нужно копать что-то в сторону типизованного жабоскрипта

То есть C++ тоже не годится.

__>он не годится для каких-то вычислений из-за корявой модели памяти.

Как связаны модель памяти и вычисления? Массив в .NET отличается от массива в C? Или ты о чем? Опять какой-то воображаемый мир у тебя.
Да и зачем тут С++, когда все вычисления пишутся на голом C?

__>он был просто создан как замена С++ для внутренних проектов Микрософта.

Опять воображаемый мир? Историю почитай чтоли. .NET создали когда Sun не допустил лицензирование виртуальной машины Java с расширениями MS.

__>Никто другой в здавом уме его использовать не будет

Чувак, ты пишешь на форуме, который на .NET, ты считаешь его создателей ненормальными?


__>С++ый проект внутри MS контролировать невозможно в принципе никаким образом.

Странно, как же Office Team уже 20 лет офис делает?

__>C# ый — да, он тормозит и еле работает, ну по крайней мере он не так часто падает. Всё остальное уже вторично

Вот тебе и ответ, изучай .NET — научишься делать программы, которые не падают.

G>>Во-первых просто не скомпилируется.

__>ну ясен пень
А зачем постить такой код, в котором ты даже сам не разбираешься?


G>>Во-вторых ты походу не знаешь разницу между auto_ptr и unique_ptr.

G>>В-третьих попробуй передать куда-либо auto_ptr.
__>auto_ptr был создан как раз с целью using — гарантированное уничтожение обьекта при выходе из scope при возникновении исключения. он был создан миллион лет назад и давно уже obsolete.

Ты упоротый чтоли? Цель using — не "гарантированное уничтожение", а только лишь гарантированный вызов dispose. Dispose может делать что угодно, даже не связанное с уничтожением.
Кстати для справки — IDisposable в .NET может реализовывать даже структура для которой нет никакого "уничтожения".
Читай учебник и не пиши глупости.


__>>>вот это повредение и пытается симулировать C# со своим Dispose

G>>Пойди учебник почитай, не пиши глупостей.
__>учебник по C#? да я лучше на шиномонтаж работать пойду, чем снова на C# писать
Ну судя по твоим знаниям — на шиномонтаже тебе самое место
Re[11]: Garbage collection vs manual memory management
От: __kot2  
Дата: 18.01.15 21:24
Оценка: -1
Здравствуйте, AlexRK, Вы писали:
__>>а смысл знать .NET ?
__>>он не годится для серверной стороны, так там там линукс везде
__>>он не годится для гуя — так как он сейчас весь вебовский и нужно копать что-то в сторону типизованного жабоскрипта
__>>он не годится для каких-то вычислений из-за корявой модели памяти.
ARK>Есть и другие места применения, помимо перечисленных. Я, помимо прочего, участвую в разработке ГИС на C#.
отличная идея. и как это собираются портировать на iphone/ipad/web? — самые быстрорастущие и денежные рынки? хотя, наверное это советский продукт, раз mac os в пролете? но даже совесткие смартфоны андроидовские

__>>он был просто создан как замена С++ для внутренних проектов Микрософта. Никто другой в здавом уме его использовать не будет С++ый проект внутри MS контролировать невозможно в принципе никаким образом. C# ый — да, он тормозит и еле работает, ну по крайней мере он не так часто падает. Всё остальное уже вторично

ARK>Тупой бред.
я там работал
Re[13]: Garbage collection vs manual memory management
От: __kot2  
Дата: 18.01.15 23:56
Оценка: -1
Здравствуйте, gandjustas, Вы писали:
G>Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
это как в Советском Союзе? Сначала создать проблему, а потом героически ее преодолевать?
Re[17]: Garbage collection vs manual memory management
От: __kot2  
Дата: 19.01.15 15:29
Оценка: -1
Здравствуйте, gandjustas, Вы писали:
G>>>>>Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
__>>>>это как в Советском Союзе? Сначала создать проблему, а потом героически ее преодолевать?
G>>>Ты не в курсе, что .net был создан сильно до того, как появились все эти платформы?
__>>а С++ когда был создан?
G>В 2011 году, все предыдущие версии безнадежно больны и практически неизлечимы (неприятные побочные эффекты, ага).
я вообще понять не могу о чем разговор даже. С++ всегда был рабочим и всегда подходил для разработки. С++ 11 это обычные мелкие доработочки, чтобы каждые свой велосипед не городили посредствами языка, стандартные решения были стандартизованы.

G>Но и это не играет никакой роли, ибо никакого универсального фреймворка, работающего более чем на одной платформе в принципе нет для C++.

G>Про Qt даже не вспоминай, выглядит как говно, в приличном обществе сразу по лицу за такое бьют.
Qt лучший фреймворк среди всех существующих.

G>В итоге вместо универсальности ты получишь N разных codebase для N разных платформ. Желаю удачи в поддержке.

я портировал С++ десктопные приложения на iphone. Раз плюнусть.

ты реально какой-то наркоман. засим прекращаю нашу тут дискуссию. не вижу смысла вообще ее вести
Re[19]: Garbage collection vs manual memory management
От: __kot2  
Дата: 19.01.15 21:37
Оценка: -1
Здравствуйте, Константин, Вы писали:
К>Ни фига себе мелкие доработки:
К>- move семантика
оптимизация — чтобы вместо по референсу по значению передавать. ну да, удобно, но ничего фундаментально нового

К>- возможность по-человечески использовать алгоритмы STL (лямбды)

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

К>- нормальный способ итерироваться по коллекциям без ужасов типа BOOST_FOREACH

я и говорю, мелкие доработки вместо своих велосипедов.

К>- std::unique_ptr (нормальных аналогов до выхода C++11 не было)

auto_ptr то же самое кроме move semantics. или я в чем-то неправ? смартпойнтеры были хорошо разжеваны еще Александреску и я использовал его локивские еще году в 2006ом. стандартизовали — молодцы. сделаи чтото новое? да нет кгнечно

К>- избавление от необходимости писать километровые имена типов (auto)

да, согласен. единсвтенная сильная доработка. впрочем, ничего фундаментально не меняющая. просто typedef писать не нужно. я лично auto ипользую в основном только для итераторов.

К>+ по мелочи variadic templates, constexpr, upgrade STL ...

ну да, мелкая хрень всякая

К>Скажу больше,

К>- если человек когда-то писал на C++, но не делает это сейчас
К>- если человек пишет на C++, но не интересуется, не изучал С++11
К>то он не знает современный C++
конечно, не знает. современный С++ такой сложный, что его никто не знает
Отредактировано 19.01.2015 21:48 __kot2 . Предыдущая версия .
Re[14]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.01.15 10:09
Оценка: -1
Здравствуйте, Константин, Вы писали:

К>Здравствуйте, gandjustas, Вы писали:


К>>>Почему костыль? Вполне себе идиома объекта с единственным владельцем.

G>>А зачем оно нужно? Единственность владельца важна в двух случаях — автоматическое удаление объекта, передача между потоками. Второе в С++ не реализовано, а первое является костылем для атоматических деструкторов, которые в свою очередь костыли для небезопасных указателей.

К>IMHO, единственность владельца облегчает понимание кода.

Это облегчает понимание C++ кода, мбо в нем владелец отвечает за овобождение памяти. В языках с GC владение нужно нечасто, только в запутанных графах объектов.

К>Владение и side эффекты связанные с этим локализованы.

Владение в C++ это вовсе не гарантия, можно из unique_ptr получить голый указатель и предать куда угодно.
Фактически единственная суть "владения" в C++ — ответственность за уничтожение.


К><offtopic>

К>С точки зрения .NET некоторые идиомы C++ могут казаться костылями. Обратное тоже верно. Не вижу смысла особо флеймить по этому поводу.
К></offtopic>
Если кажется костылями, то это и есть костыли. Но нужно отдать должное новым версиям C++, там ручное выписывание copy и move ctor почти не нужно если пользуешься правильными средствами. Все костыли надежно спрятаны внутри stl.
В ранних версиях конечно все костыли торчали наружу, что изрядно доставляло.
Re[2]: Garbage collection vs manual memory management
От: vdimas Россия  
Дата: 21.01.15 07:43
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Стандартный паттерн для таких сценариев — это приведение отношения использования из oo:1 к 1:1 и нам достаточно будет затем сделать подмену указателя только в одном месте. Делается опять же стандартно через ровно +1 к уровню косвенности...


Прошелся по остальной ветке, такое решение уже предлагали:
http://rsdn.ru/forum/philosophy/5917277
Автор: andyag
Дата: 10.01.15

http://rsdn.ru/forum/philosophy/5916590
Автор: andyag
Дата: 09.01.15
Re[2]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 08.01.15 10:46
Оценка:
Здравствуйте, s_aa, Вы писали:

>>отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств.


_>Ну и загружай новую, старая подчистится GC если ссылок нет, зачем удалять, забыл про нее и все.


А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.

Я об этом и говорю что тут токо сиди и надейся что оно сработает, нет в языке средств прямого управления временем жизни объекта.
Re[2]: Garbage collection vs manual memory management
От: Alex912  
Дата: 08.01.15 14:10
Оценка:
Здравствуйте, Abyx, Вы писали:

A>Что касается C# — никто не мешает тебе сделать weak_ptr в C#. Просто там никто так не делает, слишком неудобно/сложно.


Это что-то типо здесь ?
Re[3]: Garbage collection vs manual memory management
От: Abyx Россия  
Дата: 08.01.15 15:58
Оценка:
Здравствуйте, Alex912, Вы писали:

A>Здравствуйте, Abyx, Вы писали:


A>>Что касается C# — никто не мешает тебе сделать weak_ptr в C#. Просто там никто так не делает, слишком неудобно/сложно.


A>Это что-то типо здесь ?


да
In Zen We Trust
Re: Garbage collection vs manual memory management
От: Abyx Россия  
Дата: 08.01.15 16:08
Оценка:
Здравствуйте, johny5, Вы писали:


J>Сразу скажу тут скорее не то что вы ожидаете, это не очередной вброс о производительности программ написанных на C# и C++.

J>

J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.

J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

вообще тут проблема исключительно архитектурная.
в С# тоже можно сделать "delete". Если ты знаешь что на объект есть только одна ссылка, то присвоив ей null ты почти сразу же удалишь этот объект.
так что можно добавить дополнительную косвенность, и вместо самого объекта отдавать обертку со ссылкой на него.
In Zen We Trust
Re[2]: Garbage collection vs manual memory management
От: denisko http://sdeniskos.blogspot.com/
Дата: 08.01.15 16:43
Оценка:
Здравствуйте, Abyx, Вы писали:

A>Здравствуйте, johny5, Вы писали:



J>>Сразу скажу тут скорее не то что вы ожидаете, это не очередной вброс о производительности программ написанных на C# и C++.

J>>

J>>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.

J>>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

A>вообще тут проблема исключительно архитектурная.

A>в С# тоже можно сделать "delete". Если ты знаешь что на объект есть только одна ссылка, то присвоив ей null ты почти сразу же удалишь этот объект.
Это тоже мягко говоря не совсем так http://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx
<Подпись удалена модератором>
Re: IDisposable спасет отца русской демократии (-)
От: 0x7be СССР  
Дата: 08.01.15 18:53
Оценка:
Re[2]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 08.01.15 20:48
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>В самом худшем случае ты получишь утечку памяти.


Как раз C# приложение будет крошиться, потому что та модель которая должна бы уже умереть, всё ещё живая а значит есть какие то нити её подпитывающие. В частности подписки на UI контролы, с коими я боролся. Там нет возможности отписаться никак, а weak subscription работает ровно столько насколько ты уверен что твой объект таки умрёт.

Мне же приходилось скакать через весь код сканировать что где я подписался неправильно. В С++ модульности такое просто невозможно, каждый модуль независим. Проблема с dangling pointers в С++ есть, но обычно если модуль 1 знает что модуль 2 отключен то все такие указатели уже просто не используются. Тут нужна просто более грамотная модульная организация, но всё таки в С++ можно сказать что ООП тут работает в полную силу а в С# один спагетти код, где всё всё тянет за ручку.

Вообще это форум философии а не священных воин. Я хочу понять как другие люди кодят на C#, избегая подобных проблем. Стиль кодирования, как я тут где то читал, на C# и C++ разнится кардинально, я бы с удовольствием почитал бы как именно. С++ подход в С#, как видно, проваливается в полный рост.
Re[2]: Пара примеров
От: johny5 Новая Зеландия
Дата: 08.01.15 22:12
Оценка:
Здравствуйте, Васильич, Вы писали:

В>В обоих случаях программист обязан:

В>1. Явно закрывать неиспользуемые более ресурсы (файлы, коннекшены к БД, и т.д.)
В>2. Явно обнулять все дополнительные ссылки на удаляемый объект.

П.2 в С++ не обязателен, смотрите ниже.


В>Возьмем ваш пример с кнопкой и прикрепленным к ней звуком. В C++ никто не отменяет обязанность присвоить кнопке новый указатель на звук после рестарта менеджера звуков, соответственно у вас будет некий алгоритм по уведомлению подписанных объектов о рестарте менеджера. Абсолютно то же самое будет в C#. Никаких проблем с зависшими объектами не возникнет.


Да, тут вы правы, на самом деле в C++ для таких мало связанных систем мы бы тоже использовали какие то хэндлы. Сам хэндл правда мог бы и содержать указатель но в С# нельзя, только если это weak_ptr<> но я так понял в С# его так широко не используют.

<rant on>
Уф.. Это ж какое то наказание, за то что GC собирает для вас память вы теперь должны скурпулёзно подсчитывать ссылки для него, чтоб не дай бог где чего.
<rant off>

Окей, пара практических примеров.


Модульность


Модуль 1 подключается к Модулю 2.
Идёт обмен данными.
Модуль 2 кем то явно убивается.
Модуль 1 пытается опять подключиться к модулю 2.
Обмен данных не инициируется.

В С++ эта модульность — спасительный круг в мире висящих указателей, определённый функционал просто не будет запущен если какое то условие на более высоком уровне не было выдержано. В данном случае какой то блок внутри Модуля 1 будет просто отключен и что какие ссылки и структуры он содержит и куда оно всё ссылается оно всё становится неважно. По сути это приводит к повышению требования к качеству ООП в С++.

В C# же, модуль 2 всегда должен знать где как и кому он отдался, и возможно на Finalize сам должен уметь себя подчищать, .. и по моему небольшому опыту
Автор: johny5
Дата: 16.01.14
некоторые из этих случаев достаточно нетривиальны.

-------------------------


Копирование по значению


Тут я пытался придумать как копирование по значению в С++, поможет в данной проблеме но не нашёлся что написать... т.к. копирование, в общем случае, вызовет копирование всех ссылок внутри.
Re: Garbage collection vs manual memory management
От: __kot2  
Дата: 08.01.15 22:17
Оценка:
Здравствуйте, johny5, Вы писали:
J>Я сам С++ник и безуспешно пытался пересесть на С#. Я поимел реальных проблем с тем что я впринципе не имею никакого контроля над временем жизни объектов мной созданных. К примеру загрузил я файл в модель, отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств. Всё что тут можно сделать это подчистить везде везде везде ссылки на эту форму, на модель и скрестить пальцы что скоро всё само удалится. И всё равно не срабатывает в 50% случаях.
да, есть такой прикол — вместо delete приходится вызывать dispose. поэтому грамотная работа с памятью в C#, Java становится ничем не проще С++

собственно, я только потому питоном и пользуюсь, что там reference counting а не дурацкий непонятно как работающий GC
Re[3]: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:16
Оценка:
Здравствуйте, johny5, Вы писали:

J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.


У тебя синдром управления памятью. Для поиска "статической переменной в которую сложили весь мусор" есть довольно эффективные приложения. Случается это раз в 5 лет и ловится на раз.

Управлять нужно только неуправляемыми ресурсами. И в пример с твой кнопкой нужно тупо вызвать Dispse() который выгрузит все неуправляемые ресурсы. О памяти просто не надо думать. Она сама уйдет когда надо будет.

Работая со сложными структурами данных удержать граф зависимостей объектов в голве крайне не просто. GC позволяет просто не делать это. И это хорошо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Garbage collection vs manual memory management
От: hi_octane Беларусь  
Дата: 09.01.15 01:23
Оценка:
J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.
J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

Ну допустим смог ты delete и на две строчки ниже по этому же указателю обратился. Привет продакшн — лучший bounds checker!

И у C++ и у C# одна и та же проблема — ты можешь сделать какие-то действия (delete в C++, pointer = null в C#) и надеяться что произойдёт то что ты ожидаешь. Но трезво взгляни на вещи — ни в том ни в другом языке ты не знаешь что реально произойдёт, и в каком состоянии программа окажется после твоего delete.

Нужен механизм который бы гарантировал что после delete состояние программы полностью определено и синтаксис для описания того, что именно считать состоянием и как его определить. Как только такое чудо света кто-то придумает, так сразу и GC будет не нужен, и, внезапно, delete тоже будет не нужен. Ведь из описания такого контракта компилятору будет ясно что уже можно удалять, а что ещё нет.
Re[3]: Garbage collection vs manual memory management
От: enji  
Дата: 09.01.15 10:14
Оценка:
Здравствуйте, johny5, Вы писали:

J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.

J>Я об этом и говорю что тут токо сиди и надейся что оно сработает, нет в языке средств прямого управления временем жизни объекта.

Как будто в плюсах оно есть. Да, тут ты можешь прибить объект, но затем скаптуренный this в мелкой лямбде просто расстреляет память.

Собственно и там и там надо принимать специальные меры — каптурить прокси к примеру...
Re[2]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 09.01.15 11:01
Оценка:
Здравствуйте, andyag, Вы писали:

A>
A>class SoundManager {...} // эту штуку вы хотите убивать и делать новую

A>class SoundService : IListenToSoundManagerUpdates 
A>{
A>  private SoundManager _soundManager;

A>  public void OnSoundManagerHasChanged(SoundManager sm)
A>  {
A>    _soundManager = sm;
A>  }

A>  public void PlaySound()
A>  {
A>    _soundManager.PlaySound();
A>  }
A>}

A>winAmpButton.Click += {
A>  _soundService.PlaySound();
A>};

A>restartSoundManagerButton.Click += {
A>  var soundManager = new SoundManager("another sound library");
A>  _soundService.OnSoundManagerHasChanged(soundManager);
A>};
A>


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

Давайте тогда рассмотрим пример что я получил на практике, и решения коему пока не нашёл.

Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

Скажем так, несколько дней спустя я уже изменил все подписки на UI на weak subscription (это было сложно). И пробежал через все лямбды которые я где либо когда либо написал и кому то отдал, чтобы они неявно не каптурили this.

Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.

Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?


Ещё посмотрите пожайлуста на пост про модульность (rant можно опустить)
http://rsdn.ru/forum/philosophy/5916342.1
Автор: johny5
Дата: 09.01.15


Интересно ваше мнение.
Re[3]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:17
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>ATS же. Там все это было еще сто лет назад. Но на практике шибко сложно в использовании, дальше полутора академиков не пошло.


Rust же.
Re[2]: Garbage collection vs manual memory management
От: 0BD11A0D  
Дата: 09.01.15 12:17
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, johny5, Вы писали:


J>>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


VD>Меня забавляет твой термин "С++ профессионал". Если ты проффесионал, то наличие конкретных свойств среду для тебя не должно быть ужасом.


Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»). Распространять ужостики про другие языки — характерная часть этой профессии, потому, что язык очень часто используется неоправдано, и если этого не делать — их поувольняют и заменят более дешевыми.
Re[3]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:28
Оценка:
Здравствуйте, 0BD11A0D, Вы писали:

BDA>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).


Это не единственное, а только одно из двух значений слова "профессионал".
Re[4]: Garbage collection vs manual memory management
От: 0BD11A0D  
Дата: 09.01.15 12:39
Оценка:
Здравствуйте, AlexRK, Вы писали:

BDA>>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).

ARK>Это не единственное, а только одно из двух значений слова "профессионал".

Да, есть еще вторая (секретная) этимология — от слов «проффесор» (с двумя «ф») и «анал». Засекречена по политическим причинам.

  Скрытый текст
Смысла в этом постинге нет никакого, кроме как разбавить глупость желчью. С целью предотвращения дальнейшего падения концентрации (каждый пусть сам решает, чего) в эту подветку больше не пишу.
Re[5]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:46
Оценка:
Здравствуйте, 0BD11A0D, Вы писали:

BDA>>>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).

ARK>>Это не единственное, а только одно из двух значений слова "профессионал".

BDA>Да, есть еще вторая (секретная) этимология — от слов «проффесор» (с двумя «ф») и «анал». Засекречена по политическим причинам.


Fail.

м. 1) Тот, кто сделал какое-л. занятие своей профессией (противоп.: любитель). 2) Хороший специалист, знаток своего дела.


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


Ах, нет, только не это.
Re[3]: Garbage collection vs manual memory management
От: Sinix  
Дата: 09.01.15 12:55
Оценка:
Здравствуйте, johny5, Вы писали:

J>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

Сценарий нереалистичный (на практике время жизни модели совпадает с временем жизни ui), но ок.

Общий случай: делаем событие ModelChanged или ModelDisposed (если модель будет убиваться ровно один раз). Обработчики события подчищают лишние ссылки, проблема решена.
Если код модулей кривой и может упасть на ровном месте, придётся вместо простого вызова события получать всех подписчиков и оборачивать вызов каждого в try-catch с последующим бросанием AggregateException после вызова всех подписчиков. Иначе от утечек вы так никуда и не денетесь.


Для вашего конкретного случая: достаточно свойства CurrentModel. Код обращается к модели через это свойство, при необходимости подменить модель — меняем только значение свойства. Ну и не забываем про PropertyChanged, чтобы биндинг работал.

J>Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.

Вообще-то в wpf нет кэша. И как раз в wpf эта проблема решается элементарно — биндингом

J>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

Пытаетесь писать на шарпе в c++-стиле.
Re[3]: Пара примеров
От: andyag  
Дата: 09.01.15 13:10
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, Васильич, Вы писали:


J>

Модульность


J>Модуль 1 подключается к Модулю 2.

J>Идёт обмен данными.
J>Модуль 2 кем то явно убивается.
J>Модуль 1 пытается опять подключиться к модулю 2.
J>Обмен данных не инициируется.

А приведите пожалуйста пример из реальной жизни. Глядя на эту абстрактную иллюстрацию первый вопрос, который хочется задать — а почему, собственно, они общающтся напрямую, но при этом одного из них убивает кто-то ещё? Нужна какая-то однозначная стратегия владения ("логического владения"). Например, "модуль 1 использует модуль 2" — в этом случае модуль 1 отвечает за уместное разрушение. Или "модуль 2 использует модуль 1" — аналогично. Если оба варианта не очень похожи на правду, есть третий — "модуль 3 использует модули 1 и 2" ("...просто вы его ещё не выделили из существующего кода"). Если у вас реально "общаются 1 и 2", эта часть решения — хороший кандидат на ревью: потому что обычно это на самом деле либо 1 модуль, либо 3, но не 2 (http://en.wikipedia.org/wiki/Circular_dependency). Это не всегда антипаттерн, но _очень часто_.

J>В С++ эта модульность — спасительный круг в мире висящих указателей, определённый функционал просто не будет запущен если какое то условие на более высоком уровне не было выдержано. В данном случае какой то блок внутри Модуля 1 будет просто отключен и что какие ссылки и структуры он содержит и куда оно всё ссылается оно всё становится неважно. По сути это приводит к повышению требования к качеству ООП в С++.


Не очень понятно. Обычно отключение куска кода — это в простейшем случае if вокруг какого-то флажка. Этим флажком кто-то должен управлять. В вашей иллюстрации, скорее всего, тот самый компонент, который "кто-то, кто явно убивает модуль 2". Убийство объекта это не delete, и не вызов сборщика мусора. Это в первую очередь заявление "этот объект теперь неактуален".

J>В C# же, модуль 2 всегда должен знать где как и кому он отдался, и возможно на Finalize сам должен уметь себя подчищать, .. и по моему небольшому опыту
Автор: johny5
Дата: 16.01.14
некоторые из этих случаев достаточно нетривиальны.


Снова — ну _очень_ абстрактно. Любой хеловорлд в 10 строчек помог бы сделать разговор более предметным.

J>

Копирование по значению


J>Тут я пытался придумать как копирование по значению в С++, поможет в данной проблеме но не нашёлся что написать... т.к. копирование, в общем случае, вызовет копирование всех ссылок внутри.


И вот опять. Ну серьёзно, покажите немного кода
Re[3]: Garbage collection vs manual memory management
От: andyag  
Дата: 09.01.15 13:10
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, andyag, Вы писали:


A>>
A>>class SoundManager {...} // эту штуку вы хотите убивать и делать новую
A>>


J>Хорошо, это интересно. Посредник и правда решает эту задачу, хотя посредник будет вынужден полностью реплицировать интерфейс спрятанного им SoundManager.


Если решать в лоб, то да. Но вообще в Java/C# легко делаются всевозможные прокси объекты. Одна из популярных практик — описать какой-то "желаемый" интерфейс, а потом отдельно описать, что половина его реализации должна браться из вот этого объекта, вторая — из вон того, а третью вообще пусть фреймворк сам придумает как сделать. Посмотрите например вот сюда:
1. UserRepositoryCustom реализуется в UserRepositoryImpl
2. CrudRepository<User, Long> реализуется библиотекой
3. Из всего этого получается единственный объект с интерфейсом UserRepository, который выглядит "как надо".

J>Давайте тогда рассмотрим пример что я получил на практике, и решения коему пока не нашёл.

J>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.
J>Скажем так, несколько дней спустя я уже изменил все подписки на UI на weak subscription (это было сложно). И пробежал через все лямбды которые я где либо когда либо написал и кому то отдал, чтобы они неявно не каптурили this.
J>Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.
J>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

А сильно сложно такого поведения на коротком примере добиться? Я последний год периодически пописываю UI на WPF и (видимых?) проблем с утечками нет. У вас оно прямо реально течёт или просто не исчезает, когда вы этого ожидаете? В плане наличия проблем "вообще", единственное, что могу предположить — вы используете какую-то "идиому", которая плохо ложится на GC.

J>Ещё посмотрите пожайлуста на пост про модульность (rant можно опустить)

J>http://rsdn.ru/forum/philosophy/5916342.1
Автор: johny5
Дата: 09.01.15


J>Интересно ваше мнение.


Написал комментарий.
Re[2]: Просто сначала надо читать, а потом писать...
От: johny5 Новая Зеландия
Дата: 09.01.15 13:40
Оценка:
Здравствуйте, 11molniev, Вы писали:

1> Ссылки надо подчистить не на форму, а на модель (в С++ вы удаляете объект на который у вас ещё есть ссылки?). Срабатывает в ста случаях корректного использования (десятки лет эксплуатации .Net/Java подтверждают это).


Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.

Не нашёл подобного механизма в C#, кроме того я вабще не понял как можно там отписываться. Ввод прокси объекта и занулять там указатель, это единственный вариант сделать подобное в C#?
Re[4]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 09.01.15 13:48
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, johny5, Вы писали:


J>>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

S>Сценарий нереалистичный (на практике время жизни модели совпадает с временем жизни ui), но ок.

А тогда как вы иначе делаете Load данных с диска, убиваете и пересоздаёте форму целиком?


S>Для вашего конкретного случая: достаточно свойства CurrentModel. Код обращается к модели через это свойство, при необходимости подменить модель — меняем только значение свойства. Ну и не забываем про PropertyChanged, чтобы биндинг работал.


Прокси — понятно.


S>Вообще-то в wpf нет кэша. И как раз в wpf эта проблема решается элементарно — биндингом

Да нет, он там есть
Автор: johny5
Дата: 31.01.14
. Как раз вот это ощущение полного контроля над памятью что мы приносим из С++ и приводит к проблемам и попыткам контролировать всё в C#. Похоже в последнем нужно смириться что ты не имеешь контроля и защищаешь свои данные интерфейсами и прокси прослойками, чтобы всегда можно было бы перекрыть кран в одном узком месте.

Биндинг помоему тоже создаёт жёсткую ссылку, но тут неуверен. Как чистить ссылки биндинга — ума не приложу.


J>>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

S>Пытаетесь писать на шарпе в c++-стиле.

Понять бы что есть С# стиль..
Re[3]: Просто сначала надо читать, а потом писать...
От: Jack128  
Дата: 09.01.15 13:50
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, 11molniev, Вы писали:


J>Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.


https://www.google.ru/search?ie=UTF-8&amp;hl=ru&amp;q=c%23%20weak%20events&amp;gws_rd=ssl
Это?
Re[4]: Пара примеров
От: johny5 Новая Зеландия
Дата: 09.01.15 14:16
Оценка:
Здравствуйте, andyag, Вы писали:

J>>В С++ эта модульность — спасительный круг в мире висящих указателей, определённый функционал просто не будет запущен если какое то условие на более высоком уровне не было выдержано. В данном случае какой то блок внутри Модуля 1 будет просто отключен и что какие ссылки и структуры он содержит и куда оно всё ссылается оно всё становится неважно. По сути это приводит к повышению требования к качеству ООП в С++.


A>Не очень понятно. Обычно отключение куска кода — это в простейшем случае if вокруг какого-то флажка. Этим флажком кто-то должен управлять. В вашей иллюстрации, скорее всего, тот самый компонент, который "кто-то, кто явно убивает модуль 2". Убийство объекта это не delete, и не вызов сборщика мусора. Это в первую очередь заявление "этот объект теперь неактуален".


Да, так и есть, только этим флажком необязательно управлять извне. Модуль 1 может сам позаботиться о получении этого флажка. Да через тот же синглетон. Впрочем важно ли как этот флажок получен? Тут ведь главное что если флажок сброшен то какой то кусок модуля 1, который держит связь со 2м, не будет запущен.

Расширим тот же пример с кнопкой и звуковым менеджером. Пусть кнопка является частью музыкального проигрывателя.
Проигрыватель, для эффективности, может содержать прямые ссылки на звуки из менеджера (закешированные) и дёргать их по мере надобности. Но в момент когда ты нажимаешь кнопку "Play", проигрыватель сначала проверит всё ли окей с менеджером звуков, и если нет, выдаст сообщение об ошибке и прервёт проигрывание.

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

Код не приведу, видно что пример притянут за уши. Организм требует сна, ничего более реалистичного в голову не приходит, впрочем я уверен вполне что реальных примеров уйма. Я очень надеюсь что объяснил ясно.
Re[4]: Просто сначала надо читать, а потом писать...
От: johny5 Новая Зеландия
Дата: 09.01.15 14:19
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Здравствуйте, johny5, Вы писали:


J>>Здравствуйте, 11molniev, Вы писали:


J>>Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.


J>https://www.google.ru/search?ie=UTF-8&amp;hl=ru&amp;q=c%23%20weak%20events&amp;gws_rd=ssl

J>Это?

Было дело, искал.

Нашлось куча хаков и это, которое AFAIK не поддерживает WPF.

Похоже weak подписки пока не тренд в C#.
Re[3]: Просто сначала надо читать, а потом писать...
От: 11molniev  
Дата: 09.01.15 14:30
Оценка:
Здравствуйте, johny5, Вы писали:

1>> Ссылки надо подчистить не на форму, а на модель (в С++ вы удаляете объект на который у вас ещё есть ссылки?). Срабатывает в ста случаях корректного использования (десятки лет эксплуатации .Net/Java подтверждают это).


J>Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.


J>Не нашёл подобного механизма в C#, кроме того я вабще не понял как можно там отписываться. Ввод прокси объекта и занулять там указатель, это единственный вариант сделать подобное в C#?


Классические события C# предполагают, что время жизни объекта источника событий меньше времени жизни получателя, т.е. отписываться надо руками (желающие могут делать это из деструктора). Поскольку эти события были заложены в первую очередь для GUI, где время жизни объектов UI априори меньше времени жизни объектов реализующих логику приложения (по крайне мере, если код не лапша) то такой подход вполне логичен.

Но если на секундочку вспомнить, что boost таки библиотека, можно за пару минут найти прямой аналог boost:signal для C#: RX. Ну или при небольшом желании написать свой диспетчер событий, даже офигенно затюненгованная под многопоточность и конкретные паттерны потока событий такая штука вроде не очень сложна...
Re[5]: Просто сначала надо читать, а потом писать...
От: 11molniev  
Дата: 09.01.15 14:36
Оценка:
Здравствуйте, johny5, Вы писали:

J>>>Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.

J>>https://www.google.ru/search?ie=UTF-8&amp;hl=ru&amp;q=c%23%20weak%20events&amp;gws_rd=ssl
J>>Это?
J>Было дело, искал.
J>Нашлось куча хаков и это, которое AFAIK не поддерживает WPF.
J>Похоже weak подписки пока не тренд в C#.
Извиняюсь, что вмешиваюсь, но если вам нужны подобные штуки для отработки событий между WPF и логикой программы — значит вы все же делаете что то ну совсем не то...
Re[5]: Garbage collection vs manual memory management
От: Sinix  
Дата: 09.01.15 16:11
Оценка:
Здравствуйте, johny5, Вы писали:


J>А тогда как вы иначе делаете Load данных с диска, убиваете и пересоздаёте форму целиком?

Как правило, достаточно кода вида
class AppState
{
  public Document CurrentState;
  public event EventHandler CurrentStateChanged:

  public void Load(...) { ... }
}


UI просто обрабатывает события/изменение свойств. AppState не убивается и живёт, пока живо приложение (или форма, тут как удобнее).

J>Прокси — понятно.

Тут нет прокси Прокси — эт класс с тем же api, который перенаправляет вызовы обёрнутому объекту. Тут просто свойство.

S>>Вообще-то в wpf нет кэша. И как раз в wpf эта проблема решается элементарно — биндингом

J>Да нет, он там есть
Автор: johny5
Дата: 31.01.14
.

А это не кэш, это утечка памяти в wpf. Если не забуду, завтра поищу пример. Там скорее всего двойной баг: элементы списка не реализуют INotifyPropertyChanged + утечка из-за AutomationPeer.

В .net 4.6 обещали поправить.
Ссылки:
http://ayende.com/blog/4296/reproducing-a-wpf-memory-leak
https://social.msdn.microsoft.com/Forums/vstudio/en-US/1525407e-194b-440e-b316-93f8ff076abc/wpf-4-touch-automationpeer-windows-7-tablet-input-services-memory-leak?forum=wpf

и крышесносящий саппорт вот в этой ветке:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/33828e1b-224a-4b73-86b5-9af949f07508/installing-net-452-breaks-microsofts-recommended-disablewpftabletsupport-method-for-disabling?forum=wpf

J>Биндинг помоему тоже создаёт жёсткую ссылку, но тут неуверен. Как чистить ссылки биндинга — ума не приложу.

Не, там нет жёсткой ссылки. Зато есть баг, который приводит к утечке, если прибинденные к гриду записи не реализуют INotifyPropertyChanged.
Re[6]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 10.01.15 02:11
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, johny5, Вы писали:



J>>А тогда как вы иначе делаете Load данных с диска, убиваете и пересоздаёте форму целиком?

S>Как правило, достаточно кода вида
S>
S>class AppState
S>{
S>  public Document CurrentState;
S>  public event EventHandler CurrentStateChanged:

S>  public void Load(...) { ... }
S>}
S>


S>UI просто обрабатывает события/изменение свойств. AppState не убивается и живёт, пока живо приложение (или форма, тут как удобнее).


J>>Прокси — понятно.

S>Тут нет прокси Прокси — эт класс с тем же api, который перенаправляет вызовы обёрнутому объекту. Тут просто свойство.

Проперти в общем не защитит от проблемы, мы получим незащищённый указатель на модель в сыром виде. Модель окажется напрямую связанной со всеми UI контролами и выгрузить её не получится.
Re[7]: Garbage collection vs manual memory management
От: Sinix  
Дата: 10.01.15 09:07
Оценка:
Здравствуйте, johny5, Вы писали:

J>Проперти в общем не защитит от проблемы, мы получим незащищённый указатель на модель в сыром виде. Модель окажется напрямую связанной со всеми UI контролами и выгрузить её не получится.

Почему? AppState задаётся как DataContext окна, меняем модель — биндинг сам подхватит изменения.
Re[8]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 10.01.15 09:12
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, johny5, Вы писали:


J>>Проперти в общем не защитит от проблемы, мы получим незащищённый указатель на модель в сыром виде. Модель окажется напрямую связанной со всеми UI контролами и выгрузить её не получится.

S>Почему? AppState задаётся как DataContext окна, меняем модель — биндинг сам подхватит изменения.

Хм.. а как это в XAML могло бы выглядеть?
Re[5]: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.01.15 12:42
Оценка:
Здравствуйте, 0BD11A0D, Вы писали:

BDA>Во-первых, хороший специалист для кого? Для себя он хорош, или для работодателя? У них разные интересы (иногда диаметрально). ...


Хороший специалист — это человек умеющие реализовывать нужную функциональность, решать возникающие на этот пути проблемы. Короче, тот кто может делать дело в разумные сроки.

BDA>Ладно, едем дальше. Во-вторых, даже если они будут получать одинаковую зарплату, человек, неоправданно протащивший плюсы, обойдется среднестатистически дороже. У него больше возможностей запутать код (а раз он протащил ненужный язык, можно ли надеяться, что он не протащит и ненужный код?). Он тупо дольше будет управлять памятью и отлаживаться. Больше ошибок будет в релизе и бороться с ними сложнее. Заменить такого труднее. Все это деньги.


Когда говорят о стоимости специалиста, то ведут речь о зарплате.

С тем, что производительность труда сиплюсплюсника (скорее всего) будет существенно ниже нежели производительность столь же профессионального программиста на безопасном языке с GC никто не спорит. Точнее спорят как раз такие "сиплюсплюс-специалисты" с раздутым ЧСВ.

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

BDA>В-третьих, не будут они получать одинаковую зарплату. Разнорабочий плюсовик получает больше разнорабочего шарпея. Достаточно посмотреть объявления от одного и того же нанимателя.


Я не знаю кто такие разнорабочие. У меня достаточно примеров когда те кто пишет на шарпе получают больше своих коллег пишущих на плюсах. Зарплата скорее зависит от уровня знаний, страны, города, компании, нежели от языка на котором пишет человек.

Ну, а у зарплата губов меня мало интересует. Тут все очевидно порог вхождения в шарпа существенно ниже нежели в плюсы.

BDA>В-четвертых, я не говорил, что кто-то дешевый, а кто-то дорогой. Я сказал — ДЕШЕВЛЕ. Посмотрите объявления — до 110 шарп, до 120 плюсы. До 60 P (пэ), до 90 плюсы. Если бы плюсовикам нечего было защищать, они бы так себя не вели.


Мы вроде говорили о профессионалах/специалистах. За 60 тры, да и за 90 тыр найти спепциалиста не реально. По крайней мере в Москве или Питере. С поправкой на местность, валюту и базовую ставку это справедливо для любого места на земле.

BDA>В-пятых, как ни крути, управлять памятью требует больших знаний, а плюсы сложнее.


Это откровенная глупость. Управление памятью в ручную не требует больше знаний, так же как не требует больших знание поддержание в рабочем состоянии советских Волг. Просто это неприятная ручная работа. Да, тут нужен опыт. Да ошибиться легко, а значит нужны усидчивость, аккуратность и т.п. Но это не знания.

Человеку работающему над каким-нибудь искусственным интеллектом знания нужны куда больше. И найти специалиста способно решать такие задачи в стол раз сложнее нежели найти специалиста умеющего управлять памятью вручную.

Лично я долгое время писал на С и С++. Мог бы заниматься этим а дальше, но мне просто жалко тратить свое время на совершенно бессмысленную тупую работу вроде управление памятью и обход прочих граблей.

BDA>Извините, тут про программирование, да про философию, а я все про жизнь. Впредь все обязуюсь и больше не.


Дык, здесь "Философия программирования", а не о жизни.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Garbage collection vs manual memory management
От: _NN_ www.nemerleweb.com
Дата: 11.01.15 09:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>НЕ СВАЛИВАЙТЕ В ОДНУ КУЧУ УПРАВЛЕНИЕ ПАМЯТЬЮ И ДРУГИЕ ВОПРОСЫ ВЛАДЕНИЯ.


С этим абсолютно согласен.
Сборщик мусора решает проблему утечки памяти но никак не проблему утечек ресурсов.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Garbage collection vs manual memory management
От: chaotic-good  
Дата: 13.01.15 13:09
Оценка:
J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.

Не все объекты требуют контролировать свое время жизни. Скажем объект "соединение с БД" имеет время жизни, оно начинается после того, как ты коннектишься к БД и заканчивается после того, как ты сделаешь close. Это время жизни управляется явным образом что в С++, что в C# и Java. Просто методы разные, в С++ с этим получше, так как есть семантика значений и RAII. Есть еще время жизни объекта как куска памяти в куче, оно начинается когда ты делаешь new и заканчивается после delete. Это как раз то, за что отвечает GC. В твоем примере идет речь о первом времени жизни:

J>Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


оставить его на откуп GC будет ошибкой в Java/C#. Большинство объектов в программе, это обекты, которые могут легко управляться сборщиком мусора, это делает программирование проще не потому что не нужно удалять объекты вручную, а потому, что делает невозможным появление мертвых ссылок/указателей. Тоесть, даже если ты забыл поменять ссылку на звук в кнопке, а звуковой менеджер создал новый а старый выкинул, ссылка внутри кнопки продолжит указывать на старый менеджер.

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать на GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Несколько простых правил для перемещающих сборщиков мусора:
1) new/delete и подсчет ссылок в С++ больше подходят для долгоживущих объектов, которые создаются надолго, GC больше подходит для короткоживущих объектов, если загружаешь модель — делай это в одном месте и сразу выбрасывай ссылку на объект модели, чтобы он не попал в следующее поколение. В этом случае, сборка будет быстрой.
2) если объект долгоживущий, желательно чтобы он был неизменяемым, если ты создал крупный граф объектов, который пережил множество сборок мусора и попал в самое долгоживущее поколение, изменение объектов в нем будет приводить к полной пересборке мусора. Это противоположенно тому, что обычно делают в плюсах/Си — там лучше создавать удалять объекты пореже, чтобы не тратить время в аллокаторе. Вот например пулл объектов в GC языке будет плохо работать, обекты в пулле живут долго но инициализируются периодически заново нагружая GC, в GC языке лучше не использовать пуллы объектов а просто создавать объекты когда нужно в куче и не заморачиваться, это банально быстрее.
3) почитать статьи про IDisposable в С# (и его аналог в Java) и научиться его использовать
Re[2]: Garbage collection vs manual memory management
От: GarryIV  
Дата: 13.01.15 15:53
Оценка:
Здравствуйте, chaotic-good, Вы писали:

CG>Не все объекты требуют контролировать свое время жизни. Скажем объект "соединение с БД" имеет время жизни, оно начинается после того, как ты коннектишься к БД и заканчивается после того, как ты сделаешь close. Это время жизни управляется явным образом что в С++, что в C# и Java. Просто методы разные, в С++ с этим получше, так как есть семантика значений и RAII.


А в Java есть АОП. Для управления транзакциями и конекшенами это намного интереснее RAII.
WBR, Igor Evgrafov
Re[3]: Garbage collection vs manual memory management
От: chaotic-good  
Дата: 13.01.15 20:10
Оценка:
G>На практике это не так.
G>Основные тормоза создаются при генерации мусора. Меньше мусора == реже сборки == выше производительность даже при более дорогих сборках мусора.

И при этом лучше, когда мусор короткоживущий. Ну и не только мусор, нужно в целом о структурах данных думать с позиции GC (в том числе), стараться делать из более gc-friendly, чтобы создавать меньше работы для сборщика мусора, pointer chasing в стиле С/С++ тут до добра не доведет.

G>Пулы объектов в языках с GC работают прекрасно.


У меня был случай, когда я на практике наблюдал обратное — после выпиливания пулла и замены его на обычный new, все стало работать быстрее и приложение стало проводить меньше времени за сборкой мусора. В принципе, это становится очевидно и если просто почитать про устройство gc в .net, в msdn есть очень хорошая статья на эту тему, ты должно быть ее читал. Пулл объектов может работать хорошо, если ссылки внутри этих объектов не меняются, только данные, соответственно не дергается сборка в gen 2, но в общем случае, пуллы рекомендовать нельзя, особенно для короткоживущих объектов.
Re[2]: Garbage collection vs manual memory management
От: Privalov  
Дата: 14.01.15 07:37
Оценка:
Здравствуйте, Nuseraro, Вы писали:

N>Невозможность контролировать результирующий машинный код — неприемлемо для меня, поэтому пишу только на кошерном асме.


На асме тоже не все всегда контролируешь. По-моему, tasm не давал написать что-то типа xchg dx, ax, сразу заменяя на xchg ax, dx, потому что второй вариант на байт короче. А мне обязательно нужен был первый вариант.
Re[5]: Garbage collection vs manual memory management
От: chaotic-good  
Дата: 14.01.15 09:34
Оценка:
G>Любой код можно написать плохо. Можно считать это аксиомой. Но даже тысячи плохо написанных пулов объектов не делают пулинг с gc неэффективным.
G>Если посмотреть внтуренности .NET и Roslyn, то можно заметить, что очень часто используется thread-local пул объектов StringBuilder, который очень даже изменяемый. На Channel9 даже есть запись с teched где объясняют почему так.

И почему же так? Я запись нашел, но смотреть времени нет.

G>Bpexfnm jnc.lf — http://codeblog.jonskeet.uk/2014/08/01/object-pooling-and-thread-safety/ и далее по ссылкам.


Плохая статья, метод измерения производительности неизвестен. Он как-то бенчмаркает и потом делает выводы, но как — неизвестно. Может у него тест слишком короткий и в gen 2 этот string builder не успевает попасть.
Re[6]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.01.15 10:18
Оценка:
Здравствуйте, chaotic-good, Вы писали:

G>>Любой код можно написать плохо. Можно считать это аксиомой. Но даже тысячи плохо написанных пулов объектов не делают пулинг с gc неэффективным.

G>>Если посмотреть внтуренности .NET и Roslyn, то можно заметить, что очень часто используется thread-local пул объектов StringBuilder, который очень даже изменяемый. На Channel9 даже есть запись с teched где объясняют почему так.

CG>И почему же так? Я запись нашел, но смотреть времени нет.


Truth #3


Allocations are king

Time spent in the garbage collector harms responsiveness
Average delays ≈ (Collection rate) × (Collection cost)
Average delays ≈ (Allocation rate) × (Heap size)

Corollary: Allocate less

Less often (reduce collection rate)
Smaller, fewer long-lived objects (reduce heap size)



G>>Bpexfnm jnc.lf — http://codeblog.jonskeet.uk/2014/08/01/object-pooling-and-thread-safety/ и далее по ссылкам.


CG>Плохая статья, метод измерения производительности неизвестен. Он как-то бенчмаркает и потом делает выводы, но как — неизвестно. Может у него тест слишком короткий и в gen 2 этот string builder не успевает попасть.

Ты наверное не в курсе, что jonskeet это крутейший чувак по C#. Автор множеств книг и №1 на SO http://stackoverflow.com/users?tab=Reputation&amp;filter=all
Я его мнению доверяю больше, чем всем "экспертам" на этом форуме. И тебе советую.
Re[7]: Garbage collection vs manual memory management
От: koodeer  
Дата: 14.01.15 10:37
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Ты наверное не в курсе, что jonskeet это крутейший чувак по C#. Автор множеств книг и №1 на SO http://stackoverflow.com/users?tab=Reputation&amp;filter=all

G>Я его мнению доверяю больше, чем всем "экспертам" на этом форуме. И тебе советую.

Ага, вот только Скит сам писал, что не считает себя гуру дотнета.
№1 на SO — ну дык Билл Гейтс был номер в MS, а Джобс номер один в Apple.
Написать книгу по языку — вовсе не значит быть профи в разработке на этом языке.
Re[7]: Garbage collection vs manual memory management
От: chaotic-good  
Дата: 14.01.15 10:43
Оценка:
G>

G>

Truth #3


G>

Allocations are king

G>Time spent in the garbage collector harms responsiveness
G>Average delays ≈ (Collection rate) × (Collection cost)
G>Average delays ≈ (Allocation rate) × (Heap size)

G>

Corollary: Allocate less

G>Less often (reduce collection rate)
G>Smaller, fewer long-lived objects (reduce heap size)


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

G>>>Bpexfnm jnc.lf — http://codeblog.jonskeet.uk/2014/08/01/object-pooling-and-thread-safety/ и далее по ссылкам.


CG>>Плохая статья, метод измерения производительности неизвестен. Он как-то бенчмаркает и потом делает выводы, но как — неизвестно. Может у него тест слишком короткий и в gen 2 этот string builder не успевает попасть.

G>Ты наверное не в курсе, что jonskeet это крутейший чувак по C#. Автор множеств книг и №1 на SO http://stackoverflow.com/users?tab=Reputation&amp;filter=all
G>Я его мнению доверяю больше, чем всем "экспертам" на этом форуме. И тебе советую.

Я знаю кто это такой, читал его книгу и статьи. Суть в том, что тем не менее, дядя не публикует свои бенчмарки для этой статьи, следовательно, все что он в ней пишет — не имеет никакого значения. У него там долгоживущий string builder, который, насколько я понмю, содержит внутри себя ссылку на буфер, которая может меняться при использовании builder-а. Можно написать benchmark так, что эта ссылка не будет меняться никогда (буфер не будет ресайзиться, так как форматируется все время строка одной и той же длины), collection cost в тесте может быть очень низким, так как кроме самого теста никто не создает нагрузку на GC, поэтому полная сборка не будет отражаться на производительности. В реальном же коде все может быть совсем не как в бенчмарке. В реальном коде можно дернуть эту функцию, сформатировать что-нибудь объемное, что вызовет аллокацию и изменение ссылок в долгоживущем string builder-е, что в свою очередь вызовет полную сборку мусора, которая будет дорогой, а не дешевой как в benchmark-е. Может моя интуиция относительно этого и не верна и Скит правильно все делает, но я этому не поверю все равно пока сам не пощупаю или не увижу код теста. Вот такая вот у меня политика относительно бенчмарков

По поводу влияния остального кода на сложность и стоимость сборки мусора — это IMO главный недостаток языков с GC. Тут мы тестим фунцию и все ок, а там мы используем ее в приложении, которое имеет совсем другой характер нагрузки на сборщик мусора и получается совсем другой результат. Получается что кусок кода нельзя рассматривать отдельно performance wise и это не что иное как отсутствие модульности.
Отредактировано 14.01.2015 10:47 chaotic-good . Предыдущая версия .
Re[8]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.01.15 11:39
Оценка:
Здравствуйте, chaotic-good, Вы писали:

CG>По поводу влияния остального кода на сложность и стоимость сборки мусора — это IMO главный недостаток языков с GC. Тут мы тестим фунцию и все ок, а там мы используем ее в приложении, которое имеет совсем другой характер нагрузки на сборщик мусора и получается совсем другой результат. Получается что кусок кода нельзя рассматривать отдельно performance wise и это не что иное как отсутствие модульности.


Бред мягко говоря. Неэффективный код будет плохо работать независимо от места использования.
Просто в языках с GC надо считать не только циклы процессора, но и аллокации.
При ручном управлении памятью аллокации напрямую отражаются в CPU usage, а с GC получаются отложенные затраты.

Из той же презентации:

Truth #1


Profiles don’t lie

You can speculate and hypothesize all you want…
If you’re not measuring, you’re just guessing.


Truth #2


Good tools make all the difference

For managed code, the profiler of choice is PerfView
LMBTFY: http://www.bing.com/search?q=PerfView+download
http://www.microsoft.com/en-us/download/details.aspx?id=28567

Re[5]: Garbage collection vs manual memory management
От: mrTwister Россия  
Дата: 16.01.15 15:09
Оценка:
Здравствуйте, johny5, Вы писали:

J>Как то не возникает с этим проблемы в C++, не все мусорные указатели на самом деле используются. Кроме того, в С++ есть возможность передаваемую структуру данных скопировать by value. В С# это не подрузамевается но если сильно надо то конечно можно, только какой смысл тогда кодить на C# если там так всё сложно и ты должен думать над передачей каждого указателя и каждой лямбдой. Ничего GC тогда не облегчает а даже наоборот. Кроме того мемори лики оочень сложно искать, я потратил неделю. В случае с С++ висячий указатель выстрелил бы почти сразу.


В .NET утечки ищутся элементарно. Для этого даже никакой app verifier с gflags не нужен, достаточно просто дампа процесса, прямо от клиента или с продакшена. Даже символьные файлы не нужны. Вот в С++ — это секс, да.
лэт ми спик фром май харт
Re[2]: Garbage collection vs manual memory management
От: mrTwister Россия  
Дата: 16.01.15 15:11
Оценка:
Здравствуйте, __kot2, Вы писали:

__>да, есть такой прикол — вместо delete приходится вызывать dispose. поэтому грамотная работа с памятью в C#, Java становится ничем не проще С++


Интересно, какое отношение Dispose имеет к работе с памятью?
лэт ми спик фром май харт
Re[6]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.01.15 13:31
Оценка:
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, gandjustas, Вы писали:


G>>Хоть раз в жизни видел падение от того что хендлы кончались? Я нет, хотя есть подозрение что побольше тебя .Net приложений видел.

__>да, конечно, много раз
Тогда приведи минимальный код, который падает по этой причине. На .NET.

G>>В курсе что code analysis в студии показывает все места с незадиспозенным idisposable?

__>ну да, показывает лики. и что с ними делать?
Вызвать dispose.

__>>>в C#-Java вы начинаете писать код в стиле

__>>>using (...)
__>>>симулирую auto_ptr. а вот reference couring ptr вам не удастся никаикм образом добиться и придется мучаться технологиями многолетней давности
G>>Курил? Каким образом auto_ptr похож на using?
__>ну, это не мой ник похож на "ганджубас". а зачем по-вашему вообще нужен using если в C# все так хорошо с захватом и освобождением ресурсов системы?
Он нужен для детерминированного освобождения. Так как часто при "закрытии" хендла выполняется много действий Например при закрытии файла сбрасывается буфер на диск, при закрытии сокета — отправка данных из буфера, закрытие соединения с БД — возвращение в пул, чтобы другой поток мог его взять, а не плодить еще одно соединение.

Тем не менее если не использовать idisposable никакой утечки не случится, просто файл\сокет\соединение закроется после сборки мусора. В десктопном приложении никаких проблем от этого не будет вообще.

А еще часто используют disposable как некоторый scope Например в razor шаблоне с помощью using указывается где форма начинается и закачивается.
Re[6]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.01.15 13:33
Оценка:
Здравствуйте, __kot2, Вы писали:


G>>Курил? Каким образом auto_ptr похож на using?

__>ну, это не мой ник похож на "ганджубас". а зачем по-вашему вообще нужен using если в C# все так хорошо с захватом и освобождением ресурсов системы?

Кстати ты так и не ответил каким образом auto_ptr похож на using?
Re[10]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 18.01.15 19:27
Оценка:
Здравствуйте, __kot2, Вы писали:

__>а смысл знать .NET ?

__>он не годится для серверной стороны, так там там линукс везде
__>он не годится для гуя — так как он сейчас весь вебовский и нужно копать что-то в сторону типизованного жабоскрипта
__>он не годится для каких-то вычислений из-за корявой модели памяти.

Есть и другие места применения, помимо перечисленных. Я, помимо прочего, участвую в разработке ГИС на C#.

__>он был просто создан как замена С++ для внутренних проектов Микрософта. Никто другой в здавом уме его использовать не будет С++ый проект внутри MS контролировать невозможно в принципе никаким образом. C# ый — да, он тормозит и еле работает, ну по крайней мере он не так часто падает. Всё остальное уже вторично


Тупой бред.
Re[12]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.01.15 21:30
Оценка:
Здравствуйте, __kot2, Вы писали:

ARK>>Есть и другие места применения, помимо перечисленных. Я, помимо прочего, участвую в разработке ГИС на C#.

__>отличная идея. и как это собираются портировать на iphone/ipad/web? — самые быстрорастущие и денежные рынки? хотя, наверное это советский продукт, раз mac os в пролете? но даже совесткие смартфоны андроидовские

Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
Re[14]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.15 00:03
Оценка:
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, gandjustas, Вы писали:

G>>Ты совсем от жизни отстал? Про Xamarin и Unity вообще не слышал? А про .NET Core?
__>это как в Советском Союзе? Сначала создать проблему, а потом героически ее преодолевать?
Ты не в курсе, что .net был создан сильно до того, как появились все эти платформы?
Re[18]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.15 15:50
Оценка:
Здравствуйте, __kot2, Вы писали:

__>Qt лучший фреймворк среди всех существующих.

__>ты реально какой-то наркоман.

Из нас двоих наркоман совсем не я
Re[19]: Garbage collection vs manual memory management
От: __kot2  
Дата: 19.01.15 16:43
Оценка:
Здравствуйте, gandjustas, Вы писали:
G>Из нас двоих наркоман совсем не я
признание проблемы — первый шаг к излечению
Re: Garbage collection vs manual memory management
От: vdimas Россия  
Дата: 19.01.15 17:37
Оценка:
Здравствуйте, johny5, Вы писали:

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


Стандартный паттерн для таких сценариев — это приведение отношения использования из oo:1 к 1:1 и нам достаточно будет затем сделать подмену указателя только в одном месте. Делается опять же стандартно через ровно +1 к уровню косвенности...


J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.

J>Я сам С++ник и безуспешно пытался пересесть на С#. Я поимел реальных проблем с тем что я впринципе не имею никакого контроля над временем жизни объектов мной созданных.

Disposable паттерн тебе в помощь. Прекрасно точно так же все работает. Для особо клинических случаев, например, когда мы "что-то отдаем наружу", и "там" ожидается клиническое поведение, есть даже GCHandle, создаваемый как weak. Либо опять же предыдущий способ.


J>К примеру загрузил я файл в модель, отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств. Всё что тут можно сделать это подчистить везде везде везде ссылки на эту форму, на модель и скрестить пальцы что скоро всё само удалится. И всё равно не срабатывает в 50% случаях.


Если нет статических ссылок и прочего лишнего кеширования, то в 99.99% случаев и пальцы скрещивать не надо. А если есть, то опять же способ борьбы уже был дан.
Re[9]: Garbage collection vs manual memory management
От: Константин Россия  
Дата: 19.01.15 19:35
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Причем если ты привязывает сайд-эффект к деструктору (RAII), то появляется другая проблема, ты не можешь объект передать куда-либо, ибо вызовется конструктор копии, для которого вызовется деструктор, который вызовет эффект раньше времени. Можно, конечно, передать голый указатель , но тогда проблема со временем жизни появляется, можно передать защищенный указатель (ссылку)?


Эта рассуждение устарело после выхода C++11. Move-only типы решают вопрос передачи владения. В стандартной библиотеке пример move-only типа std::unique_ptr. Обёртка над файлом отличный кандидат на move-only:

File create_file(const string& path);
Re[11]: Garbage collection vs manual memory management
От: Константин Россия  
Дата: 19.01.15 19:53
Оценка:
Здравствуйте, gandjustas, Вы писали:

К>>Эта рассуждение устарело после выхода C++11. Move-only типы решают вопрос передачи владения.


G>Это тоже костыль для небезопасных указателй и автоматических деструкторов.


Почему костыль? Вполне себе идиома объекта с единственным владельцем.
Аналогия: сорвал яблоко, отдал другому. Для этого не нужно считать число владельцев и создавать/убивать клоны яблок.
Re[12]: Garbage collection vs manual memory management
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.01.15 20:11
Оценка:
Здравствуйте, Константин, Вы писали:

К>Здравствуйте, gandjustas, Вы писали:


К>>>Эта рассуждение устарело после выхода C++11. Move-only типы решают вопрос передачи владения.


G>>Это тоже костыль для небезопасных указателй и автоматических деструкторов.


К>Почему костыль? Вполне себе идиома объекта с единственным владельцем.

А зачем оно нужно? Единственность владельца важна в двух случаях — автоматическое удаление объекта, передача между потоками. Второе в С++ не реализовано, а первое является костылем для атоматических деструкторов, которые в свою очередь костыли для небезопасных указателей.
Re[13]: Garbage collection vs manual memory management
От: Константин Россия  
Дата: 20.01.15 09:36
Оценка:
Здравствуйте, gandjustas, Вы писали:

К>>Почему костыль? Вполне себе идиома объекта с единственным владельцем.

G>А зачем оно нужно? Единственность владельца важна в двух случаях — автоматическое удаление объекта, передача между потоками. Второе в С++ не реализовано, а первое является костылем для атоматических деструкторов, которые в свою очередь костыли для небезопасных указателей.

IMHO, единственность владельца облегчает понимание кода. Владение и side эффекты связанные с этим локализованы.

<offtopic>
С точки зрения .NET некоторые идиомы C++ могут казаться костылями. Обратное тоже верно. Не вижу смысла особо флеймить по этому поводу.
</offtopic>
Re[19]: Garbage collection vs manual memory management
От: BulatZiganshin  
Дата: 22.01.15 00:03
Оценка:
Здравствуйте, Константин, Вы писали:

К>- если человек когда-то писал на C++, но не делает это сейчас

К>- если человек пишет на C++, но не интересуется, не изучал С++11
К>то он не знает современный C++

на днях в стандарт приняли filesystem ts, так что человек незнакомый с ним — теперь тоже не знает C++
Люди, я люблю вас! Будьте бдительны!!!
Re[2]: Garbage collection vs manual memory management
От: fireton  
Дата: 22.01.15 08:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Память просто никто не выгружает. Сменил указатель на новое значение и все. Забыл про то что там было старое. Все выгружается автоматом. Нет ссылок, нет объекта.


Извините, что влезаю (я вообще на Дельфи пишу).

А что будет, если объект держит хэндл на файл с монопольным доступом? И пока не освободится, файл не отпустит. Как решить эту проблему?
Re[3]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 22.01.15 09:22
Оценка:
Здравствуйте, fireton, Вы писали:

F>А что будет, если объект держит хэндл на файл с монопольным доступом? И пока не освободится, файл не отпустит. Как решить эту проблему?


Если этот объект имеет "финализатор" (специальный метод, похожий на деструктор), и в этом финализаторе корректно освобождает "хэндл на файл с монопольным доступом", то через некоторое время — когда мусорщик решит прибраться — при убийстве объекта файл будет освобожден. Если хэндл в финализаторе не освобождается, то файл будет залочен, пока программа работает.
Re[3]: Garbage collection vs manual memory management
От: 0x7be СССР  
Дата: 22.01.15 09:23
Оценка:
Здравствуйте, fireton, Вы писали:

F>Извините, что влезаю (я вообще на Дельфи пишу).

F>А что будет, если объект держит хэндл на файл с монопольным доступом? И пока не освободится, файл не отпустит. Как решить эту проблему?
Через применение IDisposable.
Re[4]: Garbage collection vs manual memory management
От: fireton  
Дата: 22.01.15 10:02
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Если этот объект имеет "финализатор" (специальный метод, похожий на деструктор), и в этом финализаторе корректно освобождает "хэндл на файл с монопольным доступом", то через некоторое время — когда мусорщик решит прибраться — при убийстве объекта файл будет освобожден. Если хэндл в финализаторе не освобождается, то файл будет залочен, пока программа работает.


Ну то есть, пока GC не приберётся, другой объект не сможет получить доступ к файлу?
Re[5]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 22.01.15 10:11
Оценка:
Здравствуйте, fireton, Вы писали:

ARK>>Если этот объект имеет "финализатор" (специальный метод, похожий на деструктор), и в этом финализаторе корректно освобождает "хэндл на файл с монопольным доступом", то через некоторое время — когда мусорщик решит прибраться — при убийстве объекта файл будет освобожден. Если хэндл в финализаторе не освобождается, то файл будет залочен, пока программа работает.


F>Ну то есть, пока GC не приберётся, другой объект не сможет получить доступ к файлу?


Ну, как правильно выше заметили, по-хорошему неуправляемые ресурсы надо освобождать вручную с помощью IDisposable и using.
Я свой пост написал в предположении "как быть, если ручного освобождения нет". В таком случае да, придется ждать мусорщика (и, кстати, нет гарантии, что объект с хэндлом вообще будет удален).
Re[20]: Garbage collection vs manual memory management
От: Константин Россия  
Дата: 23.01.15 01:06
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

К>>то он не знает современный C++

BZ>на днях в стандарт приняли filesystem ts, так что человек незнакомый с ним — теперь тоже не знает C++

Век живи, век учись
Re[2]: Garbage collection vs manual memory management
От: vpchelko  
Дата: 23.01.15 20:51
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Здравствуйте, johny5, Вы писали:


J>В описанной ситуации в плюсах мы получим битый указатель, а шарпе мемлик, это понятно.

J>Меня вот какой вопрос больше интересует. В плюсах при использовании какого нить отладочного манагера памяти при нажатии на кнопку, ссылающуюся на убитый менеджер звуков, мы практически гарантированно AV получим и начнем править багу. А вот в .NET обработчик нормально отработает, ошибка будет логическая и возможно плохо заметная. Как с этим бороться ?

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

А по сути проблема в кривой дизайне.
Сало Украине, Героям Сала
Отредактировано 23.01.2015 20:55 vpchelko . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.