LINUX.ORG.RU

Reference counting vs C++ OOP model (non-reference counting)


0

2

Даже не знаю, как грамотно назвать вторую модель. С первой все ясно - объект retain-ится (+1) или release-ится (-1). Со второй - все как в «дефолтном» ООП в С++ - любой созданный объект имеет одного конкретного владельца (как в Qt).

Надеюсь, понятно, что я имел ввиду под обеими моделями.

И, собственно, вопрос: какие плюсы и минусы у данных моделей управления памятью, или, вернее, моделей управления существованием объектов?

Я последнее время 99% времени работаю с 1ой моделью и совершенно забыл преимущества 2ой. Поэтому, дискасс.

★★

стековерфлов полёг. дискасс :(

anonymous ()

А зачем эти модели противопоставлять? Они замечательно сочетаются. Лично я использую память так: всё, что возможно - размещается на стеке или в структурах/классах, без всяких указателей. В некоторых случаях так делать нельзя - тогда auto_ptr сотоварищи. И уж в совсем редких случаях нельзя однозначно назначить владельца и тогда применяются указатели с подсчётом ссылок. Работает быстро, надёжно, думать над памятью приходится редко.

legolegs ★★★★★ ()

С первой если обьектики юзаются в контекстах разных потоков дохрена на синхронизацию тратится.

nikitos ★★ ()
Ответ на: комментарий от nikitos

С первой если обьектики юзаются в контекстах разных потоков дохрена на синхронизацию тратится.

айфон видел когда нибудь? Он на этом построен.

bk_ ★★ ()

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

cattail ()
Ответ на: комментарий от cattail

>Вроде как по сравнению подсчет ссылок медленнее чем его отсутствие.

Существенно. Одна атомарная операция дает оверхед до 500 тактов проца.

Pavval ★★★★★ ()
Ответ на: комментарий от Pavval

Но ведь айфончик от этого не тормозит, а очень даже быстро работает. Быть может, не такой уж это и тормоз?

bk_ ★★ ()
Ответ на: комментарий от bk_

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

cattail ()
Ответ на: комментарий от bk_

Но ведь айфончик от этого не тормозит, а очень даже быстро работает. Быть может, не такой уж это и тормоз?

На одноядерном проце оверхед гораздо меньше и на него можно забить.

Pavval ★★★★★ ()
Ответ на: комментарий от bk_

айфон построен пьяной китайской женщиной, инфа 100% ))

nikitos ★★ ()

у первой – разруливать циклические ссылки нужно самому. Иногда – легко, иногда – ой как сложно. В остальном одни приемущества, особенно при наличии ARC(http://clang.llvm.org/docs/AutomaticReferenceCounting.html)

у второй – как по мне – по большей части недостатки, т.к. вообще непонятно когда именно нужно удалить объект

anonymous ()
Ответ на: комментарий от anonymous

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

А ARC я чего-то не доверяю.

bk_ ★★ ()
Ответ на: комментарий от Pavval

>На одноядерном проце оверхед гораздо меньше и на него можно забить.

на двухядерном айпаде и хз-сколькоядерном MacBookPro тормозов тоже не замечаю. Даже наоборот.

anonymous ()
Ответ на: комментарий от bk_

>Вот как раз циклические ссылки и являются, на мой взгляд, основной проблемой.

так а что делать? Тогда только сборщик мусора. Или есть способ разруливать циклические ссылки на этапе компиляции?

А ARC я чего-то не доверяю.

я тоже, только для меня он погоды не делает: я все(даже private) переменые юзаю через property, все объекты создаю как autorelease. Теперь будет даже проще.

Хотя, ИМХО, директивы препроцессору #pragma arc_enable/disable, чтобы самому разрулить память как надо очень даже бы не помешали

anonymous ()
Ответ на: комментарий от anonymous

я все(даже private) переменые юзаю через property

все объекты создаю как autorelease

А вот это очень плохо в некоторых, если не в большинстве, ситуаций:

1. Страшное нарушение инкапсуляции и все вытекающие отсюда проблемы.

2. Если нужно сделать «многомодульное» приложение, когда попользовался модулем, и выйдя из него, нужно всю его память освободить - autorelease совершенно не подходит.

Для циклических ссылкок есть два решения: s/retain/assign и грамотное их разруливание через колбеки. Второе в некоторых случаях очень сложно сделать, особенно с унследованным кодом. Первое же - некрасиво, однако, просто работает.

директивы препроцессору #pragma arc_enable/disable, чтобы самому разрулить память как надо очень даже бы не помешали

Я думаю, такое будет, как иначе.

bk_ ★★ ()
Ответ на: комментарий от bk_

Я думаю, такое будет, как иначе.

ARC may be explicitly enabled with the compiler flag -fobjc-arc. It may also be explicitly disabled with the compiler flag -fno-objc-arc. The last of these two flags appearing on the compile line wins.

bk_ ★★ ()
Ответ на: комментарий от anonymous

На одноядерном проце оверхед гораздо меньше и на него можно забить.

на двухядерном айпаде и хз-сколькоядерном MacBookPro тормозов тоже не замечаю. Даже наоборот.

Про 500 тактов на атомарную операцию (CAS) я сказал. Дохуядерных Интелов в первую очередь касается. А там уже от приложения зависит.

Pavval ★★★★★ ()
Ответ на: комментарий от bk_

>1. Страшное нарушение инкапсуляции и все вытекающие отсюда проблемы.

будь добр, поясни подробнее

2. Если нужно сделать «многомодульное» приложение, когда попользовался модулем, и выйдя из него, нужно всю его память освободить - autorelease совершенно не подходит.

в смысле? загрузить динамическую библиотеку в память, выполнить код неё, выгрузить? Я, в основном, пишу под iOS и тут все нужно линковать статитечски, так что не особо волнует.

Для циклических ссылкок есть два решения: s/retain/assign и грамотное их разруливание через колбеки. Второе в некоторых случаях очень сложно сделать, особенно с унследованным кодом. Первое же - некрасиво, однако, просто работает.

ну да, все зависит от случая. Но я, все-таки, очень жду когда MacRuby допилят

anonymous ()
Ответ на: комментарий от Pavval

>Про 500 тактов на атомарную операцию (CAS) я сказал. Дохуядерных Интелов в первую очередь касается. А там уже от приложения зависит.

слушай, какого ты от меня ответа ожидаешь? Да мне бо бую сколько там тактов на атомарную операцию, есть простой факт: двухядерный iPad2 работает заметно быстрее чем одноядерный iPad, что я тебе и озвучил

anonymous ()
Ответ на: комментарий от anonymous

Вот именно, чего от тебя ожидать. Молчи лучше, если по теме нечего сказать.

Pavval ★★★★★ ()
Ответ на: комментарий от anonymous

иди дальше считай свои такты

Ааа, быдлокодер... Сразу бы сказал.

Pavval ★★★★★ ()
Ответ на: комментарий от Pavval

> Про 500 тактов на атомарную операцию (CAS) я сказал.

Откуда цифра 500?

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Про 500 тактов на атомарную операцию (CAS) я сказал.

Откуда цифра 500?

Perfbook, замеряли на Opteron 844. Цифра для cache miss. В лучшем случае 60, но не надо забывать, что кеши всех остальных ядер при этом сбрасываются (что провоцирует новые cache miss'ы при конкурентном доступе). В общем атомарные операции не такие и дешевые.

Pavval ★★★★★ ()
Ответ на: комментарий от Pavval

>> Откуда цифра 500?

Perfbook, замеряли на Opteron 844. Цифра для cache miss. В лучшем случае 60

Ну то есть не «по 500», а «до 500 тактов в худшем случае». Если учесть, что атомарные операции для подсчета ссылок нужны только при создании/уничтожении/присваивании «умных указателей», то... ну ты понел.

кеши всех остальных ядер при этом сбрасываются

Наверное, ты хотел сказать «строки кэша, содержащие счетчики»?

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Наверное, ты хотел сказать «строки кэша, содержащие счетчики»?

Естественно.

Ну то есть не «по 500», а «до 500 тактов в худшем случае».

60-500, да. Но если строить на них синхронизацию, то скорее 500, я имел ввиду этот случай как пример того, почему не стоит бездумно увлекаться reference counting.

Если учесть, что атомарные операции для подсчета ссылок нужны только при создании/уничтожении/присваивании «умных указателей», то... ну ты понел.

В Qt к примеру implicit sharing везде и объекты присваивают на каждый чих. И это именно тот случай, когда это стоит учитывать.

Pavval ★★★★★ ()
Ответ на: комментарий от Pavval

>> Ну то есть не «по 500», а «до 500 тактов в худшем случае».

60-500, да. Но если строить на них синхронизацию

Причем тут синхронизация?

В Qt к примеру implicit sharing везде и объекты присваивают на каждый чих. И это именно тот случай, когда это стоит учитывать.

«Случай, когда это стоит учитывать» - это когда произведен замер, и он показал хотя бы 1% на подсчет ссылок.

tailgunner ★★★★★ ()
Ответ на: комментарий от anonymous

>1. Страшное нарушение инкапсуляции и все вытекающие отсюда проблемы.

будь добр, поясни подробнее

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

>2. Если нужно сделать «многомодульное» приложение, когда попользовался модулем, и выйдя из него, нужно всю его память освободить - autorelease совершенно не подходит.

в смысле? загрузить динамическую библиотеку в память, выполнить код неё, выгрузить? Я, в основном, пишу под iOS и тут все нужно линковать статитечски, так что не особо волнует.

Нет, линковка тут не причем. Например, у тебя есть два UIViewController-а. Причем, создание обоих влечет за собой создание огромного количества самых разных других объектов. Но при старте юзеру дается кнопка а-ля свитчер, которой он и определяет, какой модуль приложения загрузить: 1ый или 2ой (соответстсвенно, 1ый или 2ой viewcontroller).

И тебе не нужно, чтобы классы, созданные для полноценной работы 1го VC висели в памяти при текущей работе 2го, и наоборот. Именно поэтому autorelease совершенно не подходит в таких методиках. И меня, признаться, иногда сильно заебывало вычищать такие авторелизы в коде, который писался под одну задачу, которая работает одна и только одна. А когда приходится ее объединять с другой более массивной архитектурой, авторелизы, мягко говоря, усложняют ситуацию.

bk_ ★★ ()
Ответ на: комментарий от tailgunner

>> Ну то есть не «по 500», а «до 500 тактов в худшем случае».

60-500, да. Но если строить на них синхронизацию

Причем тут синхронизация?

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

Я думаю, именно это он и хотел сказать.

ОДнако, тогда у меня вопрос (скорее, риторический): атомарная операция не должна быть слишком медленной из-за этого. Собственно, на айпаде-айфоне атомарные операции весьма быстры (на глаз). Как их замерить реально?

bk_ ★★ ()
Ответ на: комментарий от bk_

ОДнако, тогда у меня вопрос (скорее, риторический): атомарная операция не должна быть слишком медленной из-за этого. Собственно, на айпаде-айфоне атомарные операции весьма быстры (на глаз). Как их замерить реально?

При одном ядре это обычные операции. При двух - хвостострел всё правильно сказал, «очень не всегда» это важно. Если интересно, то создай тестик.

Pavval ★★★★★ ()
Ответ на: комментарий от bk_

Дай идею или код.

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

Pavval ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.