Pull to refresh
-11
0
Руссков Андрей @Antervis

Разработчик

Send message

Ну давайте сначала

хорошо, в четвертый раз...

Допустим, в обоих случаях у нас есть внятная стратегия обработки ошибок

так я и утверждаю что её нет! Вы либо предусмотрели возможность ошибки типа X (в нашем случае выхода за границы массива), добавили доп. условие и предотвратили возникновение этой ошибки. Либо вы эту ошибку не предусмотрели, и соответственно забыли добавить для неё корректную обработку. И тогда лучшее, на что вы можете надеяться - что ошибка типа X улетит в обработчик ошибки типа Y, который волшебным образом сделает что-то отдаленно логичное для конкретной ситуации. В худшем случае последствия будут печальнее проезда по памяти.

я после 8 лет на плюсах начал писать еще на c# 1.1
Радовался как дитя

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

вопрос-то в том, что во втором случае пофигу, есть она у меня или нет

я уже дважды привел кейс где объяснял насколько это совершенно не "пофигу"

почему? Если у меня нормальная стратегия обработки ексепшенов, я при вылете оного спокойненько аварийно заглушу станцию

Это если вы предусмотрели "нормальную стратегию обработки" исключений конкретного вида, сигнализирующих о кейсе, который вы явно не предусмотрели. Чувствуете противоречие?

теоретически - да
А на практике - очень даже. Потому что сбор мусора происходит редко

чем реже запускается сбор мусора, тем больше ресурсов надо почистить, тем больше времени уходит на чистку. По сути это просто некоторые N% времени потраченные на GC. И этот N >> 0

именно это оно и значит:))

попробуйте написать что-то сколь угодно сложное на таком примитивно-тривиальном ЯП как баш и вы поймете о чем я

ну так давайте не питон возьмем, а сишарп, или там, свят-свят, жаву

ну так они на порядок сложнее питона, что в очередной раз подтверждает мой аргумент

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

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

а в сишарпе это просто деструктор

который вызывается когда конкретно?

финализация идет в отдельном потоке, о чем вы?

синхронизированным с остальными, что ведет к их замедлению. Плюс, количество "отдельных потоков" и ресурсов CPU на их исполнение в общем случае не бесконечно.

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

вот беру я рабочий ноут с CLion, вижу потребление RAM в 2.5 Гб, тыкаю "очистить", вижу 850Мб. Система репортит потребление CLion'а в 4.5 Гб + 1.3 Гб clang code model. Естественно настроен ShenandoahGC + ExperimentalVMOptions + GuaranteedGCInterval, т.к. без этого потребление памяти CLion'ом достигало 13 гигов а при инициации чистки мусора можно было смело идти пить чай. И ладно бы это было раз в день, а не каждые 1-2 часа. Вся эта память могла бы использоваться на что-то полезное, например на браузер. Вот это частный случай, или всё-таки общий?

У меня сложилось впечатление, что 0xd34df00d тупо убил часть своего детства и всю свою молодость на задрачивание C++ и долгое время был вынужден использовать только C++. Даже там, где у этого могло и не быть смысла. А потом, в какой-то момент, он открыл для себя дивный чудный мир за пределами его старого узкого мирка и у него слегка снесло крышу.

и в итоге зачастую сравнивает с++98/03 с языками, появившимися после с++11/14. Я почти уверен что никто из здесь присутствующих не хотел бы разрабатывать на тех же джаве/шарпе версий 2000-ного. То есть аргументы вроде как правильные, но они рисуют картину, которая от реальной разработки на современных плюсах отличается как небо и земля.

Надежность определяется как тем, делает ли программа какую-то незапланированную фигню (выходит за пределы массива), так и тем, диагностируется ли эта незапланированная фигня или же нет (отсутствие диагностики как раз снижает надежность), так и тем, есть возможность среагировать на диагностику.

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

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

в тех языках страдает еще и применимость. Смысл спорить какой язык, A или B, подойдет для задачи X лучше, если B для этой задачи в принципе не применим?

На что, собственно, я и ответил, что плохо оно это даёт, типы лучше.

т.е. по свойству транзитивности типы лучше GC?

Если у меня есть условный торговый бот

а если не торговый бот, а условная АЭС, то варианты 2 и 3 абсолютно иррелевантны - после катастрофы задача "не допустить сбой" провалена. АЭС конечно же редкий случай, но если проект может позволить себе failsafe, то опять же варианты 2 и 3 практически иррелевантны.

Объясните для тупых, как код будет продолжать работать после того, как гипотетический operator[] кинет здесь ошибку?

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

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

В плюсах оно не прерывается экзепшоном. Как это «так же»?

пишите at, будет прерываться.

Это не граница, это спектр.

где-то я это уже слышал. Правда, тот раздел психологии перестали преподавать в вузах.

Что вообще такое рефкаунт в иммутабельном случае? Как там счётчик выглядит, что вы модифицировать собрались?

рефкаунтинг всегда делают "под капотом", так, что снаружи выглядит словно инстанс не меняется. И я всё еще не понимаю чего вы от меня добиваетесь. Хотите чтобы я спроектировал функциональный язык без GC?

как сегодня нет c++ ide

QtCreator же

В дискуссии о методах управления ресурсами.

GC не является "методом управления ресурсами", а только лишь памятью.

Нет, код не работает некорректно.

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

Код вообще не работает, потому что его выполнение прервалось экзепшоном.

"Прервалось экзепшном" != "не работает". Максимально вероятно код будет продолжать работать каким-то не запланированным способом. Так же как и в плюсах. Но у вас почему-то в одном языке в выходе за границу массива будет виноват программист, а в другом языке - сам ЯП. Где в вашем сознании пролегает та самая эфемерная граница, их разделяющая? Возможно это банальная предвзятость?

Очень по значению, ага.

От того, что вы указатель завернули в класс и класс передаёте по значению, вся программа в «только по значению» не превратилась.

Я не понимаю чего вы от меня добиваетесь. Я ж говорю - передавать объекты в функции в абстрактном чисто функциональном языке можно практически как угодно. Вроде логично, что любой иммутабельный объект можно сделать refcounted, реализуя тем самым его копируемость.

Могут, в одном из следующих случаев:

  1. программа работает недостаточно долго чтобы инициировать GC до окончания. Это совершенно не наш случай.

  2. используя инкрементальные или параллельные алгоритмы. В первом случае вводится куча мелких STW, однако достаточно больших, чтобы как минимум ставить под сомнение применимость в latency-critical приложениях. Во втором случае вводятся дополнительные синхронизации потоков, чего мы в latency-critical приложениях тоже не хотим.

  3. Управляем памятью вручную. По мне так это лучше делать в языке, изначально под это заточенным.

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

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

в дискуссии о полезности GC?

Хочу сказать, что в managed-языках без unsafe выход за границы отлавливается и не является UB.

Это всё еще ошибка, она всё еще допущена, код всё еще работает некорректно. Более того, для неожиданных исключений обычно отсутствует нормальная обработка. В итоге приложение приложение уходит в некоторое некорректное состояние, в котором может застрять до рестарта (недавно ловил такое). По мне так лучше краш + рестарт.

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

Нет. Имеет смысл рассматривать языки, которые без GC реализуются тяжко (функциональщину там всякую).

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

Ну ещё раз, скопируйте мне соединение с БД.

shared_ptr<DBConnection> conn(otherConn); ?

Тока не говорите, что здравый смысл - это а) как повезет б) в сложных codebases вручную все проконтролировать невозможно

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

Что до здравого смысла - он ведь не дает вам например выпрыгнуть из окна, верно?

а так?

вы видите тут вызов копирующего конструктора?

Ну вот моих 18 лет опыта, очевидно, недостаточно. Практика дырок в других приложениях показывает, что там тоже недостаточно.

опыт коммерческой разработки с 12 лет то?

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

проблема лайфтаймов ортогональна GC и решается без него (как в том же расте)

А зачем вы спорите с соломенными чучелами? Давайте лучше сравним количество висячих ссылок, выходов за границы и так далее.

хотите сказать в managed языках не бывает выхода за границы?

Зачем похожесть на плюсы? Императивно-нулловая философия накладывает свои ограничения.

так вся дискуссия про то, насколько полезен GC. Соответственно желательно сравнивать языки, которые максимально близки во всем, кроме наличия/отсутствия GC.

А если я его после этого сохранил как поле объекта?

вариантов уйма же, самый простой - копирование.

Я не то что забываю, я изначально во всех этих солидах не шарю, там сложно чё-т слишком.

вы постоянно находите простейшие вещи невероятно сложными... И наоборот

Плюс, attention span у людей ограничен. Если мне нужно думать о плюсовых UB, то у меня остаётся меньше ресурсов на обдумывание логики.

Во-первых, это вопрос опыта разработки на конкретном языке, во-вторых, логика и реализация продумываются на разных этапах?

Часто засовываете в std::optional всякие unique_ptrы или соединения с БД, и не для ленивой инициализации, а для того, чтобы один unique_ptr потом заменить другим?

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

Как часто они там встречаются?

как часто null deference встречается в современных плюсах? В тех, где сырые указатели в принципе используются сильно реже ссылок и умных.

У вас мир C#/Java ограничивается, что ли? Должно быть, это очень грустный мир.

это самые яркие примеры языков общего назначения с GC, которые в остальном похожи на плюсы. Не с полумертвым D же сравнивать.

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

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

SRP вообще имеет смысл-то так? А то ведь для любого описания функциональности есть уровень абстракции, где это единый юнит.

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

А во-вторых, забываете что принципы SOLID это просто свод указаний, а не жестких законов.

Что касается результатов для M1 Max, то он брал их из других обзоров. Данные по Cinebench R23 были взяты из обзора на Anandtech, например.

как он мог "из других обзоров" взять время экспорта его проекта?

Например, в тесте Pugetbench для Adobe Photoshop ...

В тестах Adobe After Effects ситуация схожая ...

В Adobe Premiere Pro ... мы видим что действительно ноутбуки на Intel 11800H + 3060 справляются с экспортом видео быстрее

В DVR/FCP экспорт видео быстрее чем в premiere pro, но вы это второй раз игнорируете. По сути вместо сравнения железа вы фокусируетесь на поиске софта, в котором железо apple проигрывает. Грубо говоря, вся ваша аргументация умрет если* Adobe получше оптимизирует свой софт под apple silicon.

*я думаю скорее "когда", но не могу быть в этом уверен

В играх сравнивать в принципе не имеет смысла, поскольку там все печально.

В играх проблема в том, что под metal AAA тайтлы не оптимизируют. Так-то могёт по идее (по ссылке сравнение 8-ядерного M1Pro с 3050ti в ноутбуках одной ценовой категории)

для "системы с низкой задержкой" stop the world от GC фатален. И избавляться от него в джаве дороже, чем писать на плюсах...

Естественно, потому что любая последовательность событий освобождения ресурсов в GC может быть повторена вручную

а еще любая последовательность событий поверх аллоцировал/освободил является избыточной с точки зрения управления памятью. С++ позволяет мне этим ограничиться.

Однако, вы оставляете тут за скобками вопрос потребных человеческих ресурсов. Не надо так.

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

Часто встречаете такой код для T ~ std::unique_ptr<T'> или myDbConnection?

сформулируйте вопрос иначе

Но на плюсах писать код с хоть какой-то степенью осознанности и уверенности нельзя.

define "какой-то степенью" потому что большая часть спектра возможных интерпретаций противоречит моему опыту. Вот буквально сегодня столкнулся с "invalid memory address or nil pointer dereference" в go приложении. Значит ли это что писать на go с "какой-то степенью осознанности и уверенности" тоже нельзя? Но ведь такие ошибки бывают и в c#/java, что про них? "А если нету разницы, зачем платить больше?" (с).

Ну а вот в ФП с точки зрения перформанса объекты принимаются по ссылке, а не по значению (с точки зрения семантики это неразличимо в ФП, понятное дело)

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

Там, где объект начинает отвечать и за абстракцию над fd, и/или за конкретный специальный случай обычных файлов на диске. Это разные вещи.

я волен инкапсулировать объект любым удобным мне образом. Захочу - сделаю тонкую обертку над дескриптором. Захочу - это будет представление "файла на диске". Или "файла на диске и/или в памяти". Или "файла лежащего по абстрактному URI". SRE не нарушится ни в одном из случаев, это всего лишь разные уровни абстракции.

Мы обсуждаем производительность или корректность?

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

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

Ну а когда RAII ещё срабатывает?

когда мы удаляем объект любым способом. Например, я же не выхожу из скоупа когда делаю optional<T>::operator=(nullopt), но эта операция удаляет вложенный объект при его наличии, вызывая его деструктор.

C++ приучил :(

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

Не понял, почему это?

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

Плюс, ФП ≠ иммутабельность. В этих наших хаскелях вполне есть локальная мутабельность ...

мутабельность в ФП это бекдор, противоречащий парадигме. Собственно, поэтому и имеет смысл её локально ограничивать.

Ничему не мешает, просто показывает, что SRP таки нарушается.

можете показать где конкретно нарушается принцип единственной ответственности? Вот хоть убей не вижу.

RAII не даёт ничего, кроме, по факту, «выполни вот этот код при выходе из скоупа»

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

Такие гарантии (вместе с предсказуемым потреблением ресурсов) дают только типы.

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

А потом вы захотите управлять не только файлами на диске, но и чем-нибудь mmap'ленным, например, и понятие дескриптора файла надо будет как-то выносить отдельно.

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

Information

Rating
Does not participate
Location
Томск, Томская обл., Россия
Date of birth
Registered
Activity