Pull to refresh

Comments 22

Выскажу крамольное мнение.

На мой взгляд, старик Оккам в гробу вертится сейчас.

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

Не кажется все это странным? Ради чего вот это все вот?
Я писал на D физический симулятор реального времени для применения в играх. В нём не понадобилось отключать или как-либо особо задумываться над GC, всё просто работало. Предыдущая версия на C++ содержала свои коллекции и аллокаторы, была заметно сложнее в этом аспекте, но работала медленнее. Удобство написания кода позволяет больше времени уделять алгоритмам.
Это я к тому, что GC удобен, а ситуаций, где с ним надо что-то делать не так много. Обычный программист на C++ не пишет свои аллокаторы (разве что использует готовые простые решения), так же и обычно на D не надо вспоминать про особенности сборки мусора.
Весь цикл статей как раз про то, что не надо бояться GC, потому что вам его хватит, а если нет, то даже за его пределами есть жизнь.
А я занимался разработкой систем с гарантированным временем отклика. И часть кода сознательно писалась на чистом С (без всех этих коллекций и аллокаторов) потому что так все работало быстрее. А речь там шла о том, что нужно было некоторые вычисления уложить в очень короткие таймауты. И цена ошибки была не лаг в игре, а полный вылет протокола обмена с удаленным устройством. Т.е. это сразу рассматривалась как аварийная ситуация — нет ответа в течении таймаута — перепосылка. Несколько неудачных перепосылок — переинициализация соединения с посылкой аварийного сообщения «нет связи».

При всем при этом мы не могли себе позволить выставлять требования к железу как в современных играх — «террабайт оперативки и 256 ядер процессора». Все должно было работать на весьма скромном офисном компе (все это стабильно работало начиная с селеронов паруядерных и парой гигабайт оперативки).

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

Бела в том, что разработчику все меньше и меньше приходится «включать мозг». Все основные алгоритмы тащатся в фреймворки. Работа с памятью прячется подальше. ЧТо остается на долю разработчика? Да ничего практически.

Сейчас вот работаю с мейнфреймами. Высоконагруженные системы. Так вот, проще взять человека без опыта и научит всему с нуля, чем «с опытом» новомодных языков — переучивать такого сложнее, а код, что они выдают… Там в подкорке привычка что кто-то как-то за тобой и мусор подберет и алгоритм подходящий уже где-то реализован…
Спору нет, hard realtime это точно не про GC. Но согласитесь, это очень маленькая ниша и там себя неплохо чувствует C. Там есть средства и время на разработку.
А вот с тем, что GC из D может приводить к требованию 256 ядер процессора для простой игры, я не соглашусь. Люди пишут говнокод независимо от языка и фреймвёрка. Если бы не было js или C# с Unity, в такой же среде даже на чистом C написали бы то же самое, такое же медленное, но дороже. Более того, я уверен, что при равных трудозатратах код на C будет медленнее кода на D и, возможно, C#. C быстр тогда, когда на него тратят силы, а когда тяп-ляп и в прод, будет ад.
И нет, это не разработчики обленились и не хотят «включать мозг». Это запрос рынка на тяп-ляп, js, electron… ой, у нас анимация мигания курсора проц съела. Если качество кода не ценится, то язык не поможет. Административные проблемы техническими средствами не решаются.
Ну… У нас не было жесткого реалтайма. Было гарантированное время отклика, это немножко другое.

Просто система была распределенной и были определенные протоколы обмена. Там очень много ограничений было связано с тем, что на другой стороне стоит однокристаллка с крайне ограниченными ресурсами. И надо было по факту приема от нее сообщения быстро его провалидировать и отправить квиток чтобы она его могла удалить, освободив память для новых событий. Не успел в таймаут — оно считает что сообщение не получено и перепосылает его снова.

Писать говонкод на С сложнее — он сразу дает по мозгам и падает. Можно написать коряво, но без ошибок. Ошибок С не прощает от слова совсем.

В целом тенденция идет к утяжелению софта. Всего. Когда-то я на 4-м пне под Win2000 с гигабайтом в голове себя чувствовал очень комфортно. Сейчас пот Win10 в голове 16 гиг и не скажу чтобы этого было много. А что толку? Ничего принципиально нового. А сейчас еще и сборка и отладка не на рабочей машине идет, а на сервере. Т.е. рабочая машина фактически терминалом работает. Куда память уходит? Да на всякие финтифлюшки которые по факту жизнь не сильно упрощают.

Кому-то было лен написать нормальную IDE — сваяли эклипс на жабе. Тяжеленная хреновнина, а еще периодически лагать начинает (привет сборщику мусора).

И альтернативы нет т.к. некоторые специфические для AS/400 (платформа под которую пишу) есть только в RDi (IDE на базе Eclipce для разработки под эту платфому). Ну что-то можно на VSC делать, но не все…

И не соглашусь что это чисто административные проблемы. Отчасти да. Но отчасти и потому что половина вчерашних школьников, кое-как освоивших таблицу умножения, ломится в «разработчики» потому что там хорошо платят. И всем находится место, увы…
И не соглашусь что это чисто административные проблемы.
Да, это еще и социально-экономическая проблема: расширение доступа к разработке дуракам не таким талантливым людям.
Ну вот в целом все это не нравится мне. Во многих отношениях.

Скорее выкинуть на рынок сырой продукт чтобы застолбить место

Создавать монструальные фреймворки на все случаи жизни (а универсальность это всегда оверхед) с попыткой как можно больше скрыть от разработчика и оставить ему только «кубики» из которых лепится некая конструкция…

Все просчеты эффективности свалить на пользователя — «у вас комп слишком слабый».

Я не скажу что категорически против сборщиков мусора, но с моей точки зрения это некая крайняя мера, предохранитель в предаварийной ситуации. И сам факт что он сработал говорит об ошибках разработчика. Но за выделением и освобождением памяти разработчик должен следить сам.
Вот это выкидывание на рынок мне, да и не только мне, тоже не нравится. А точнее разработка под такой рынок. Но боюсь, это примерно того же порядка, что и «мне не нравится вода, потому что она сырая». Это же не заговор злых менеджеров по продажам, это объективные рыночные условия, так что приходится расслабляться и получать удовольствие.
А вот должен ли разработчик сам следить за памятью — это уже интересный технический вопрос. Тот же rust отлично показывает, что даже под жёстким контролем и гарантиями языка, человек не может точно управлять временем жизни объектов. Иначе там бы не появился счётчик ссылок. То есть есть ситуации, когда время жизни не очевидно и зависит от разных условий. И тогда это становится выбором между счётчиком и сборщиком. И оба не идеальны. Так что я бы не называл это ошибкой, скорее рекомендацией обойтись без автоматического управления, когда хватает ручного. В терминах C++ это использование uniq_ptr вместо shared_ptr, в D — @nogc, в C# struct, где это возможно.
Особенно ярко проблема заметна не на памяти, а файловых дескрипторах и прочих ресурсах, которые сборщик не трогает. Они должны управляться предельно просто и детерменировано. Но там и циклических ссылок нет.
… с попыткой как можно больше скрыть от разработчика и оставить ему только «кубики» из которых лепится некая конструкция…
Это бы даже приветствовалось, если бы кубики были нормальные (т.е. такие, которые заботятся о ресурсах пользователя).
Писать говонкод на С сложнее — он сразу дает по мозгам и падает.

Или не сразу, а предварительно пройдя по памяти и попортив её.

UFO just landed and posted this here
Ну у нас попроще. Микросекунда на валидацию входящего сообщения и отправку квитка отправителю и еще пара-тройка микросекунд на обработку и раздачу конечным получателям. Но у нас было очень скромное железо (двухядерный селерон 1.7ГГц + 2Гб оперативки было нормой).

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

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

Что касается темплейтов… В 90% случаев прекрасно без них обходился. И сейчас пользуюсь очень редко.

Это не лень каких-то разработчиков, а требования рынка. Время, которое вы тратите на ручное управление памятью — это время, которое вы могли потратить на разработку новых фич. Поэтому и имеем то, что имеем.


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


И потом, если для вас превыше всего производительность, то для кого-то на первом месте безопасность и корректность кода. И для них C — корень всех зол, а языки, выполняющиеся в виртуальной машине, — послание с небес.

UFO just landed and posted this here
Что есть «безопасность и корректность кода»? И как это соотносится с языком?

Есть языки, которые позволяют писать «безопасный и корректный код» левой ногой, не задумываясь, а на других нужно прикладывать некоторые мысленные усилия? Вы это имеете ввиду?

То, что в некоторых современных языках можно динамически создать объект и потом наплевать на него — сам как-нибудь уберется сборщиком мусора — это считаете нормальным? По мне так это раздолбайский подход к разработке. Из разряда «динамической типизации» — берем букву и используем, а там уж пусть сам компилятор догадается что это у нас переменная такая и придумает для нее наиболее подходящий тип. Зато разработчик сможет больше «о высоком» думать (например, где бы сегодня вечером пивка попить).

Все-таки, процесс разработки требует дисциплины внутренней. И если вы создаете объект, то должны сразу понимать где вы его будете использовать и когда он вам станет не нужен.
UFO just landed and posted this here
А в каком из языков есть принципиальные на то ограничения?

Ну вот как думаете, на каком языке написано микроядро QNX (да и все остальное, что вокруг этого микроядра крутится)? Которая, кстати, сертифицирована и по безопасности и по уровню недокументированных свойств и еще черт знает по чему и используется от автомобильных бортовых систем и до военных беспилотников и управлению АЭС.

Что там внутри? Java? Rust? Go?

И что на «безопасных языках» написано сопоставимое по уровню требований к безопасности и устойчивости?

Я к тому что разработка безопасного кода это в любом случае сложный и трудоемкий процесс. И начинается он с разработки архитектуры (и там не проходит модный нынче Agile — слишком многое надо продумывать заранее и потом следовать намеченному плану чтобы все не пошло вразбежку и не рухнуло под тяжестью придуманных по дороге фич). А язык… Это даже не вторичный вопрос.

Ну мне так кажется исходя из моего опыта. Могу ошибаться.
UFO just landed and posted this here

Занимаюсь разработкой систем мониторинга оборудования, платформа в основном arm. Один из последних продуктов написан на D, работает на железке с 256Мб оперативы и занимает из них всего 4% (около 10Мб). При этом никак сборщик мусора не модифицировал, просто писал код аккуратно (советы из статьи в этом плане очень полезны). Гипертрофировать не нужно, GC в D не такой страшный, зато даёт спокойствие и радость при написании кода =)

Просто у тебя есть выбор способа написания кода, где ГЦ не используется. Далеко не во всех языках «так можно было» (С)
10Мб — это очень много для встраиваемых систем. Попробуйте поработать с однокристалками STM32, к примеру, или Atmel.

А спокойствие и радость дает понимание как оно работает внутри :-) А не надежда что вот этот вот черный ящик будет подгребать все твои косяки.

Странное предложение "попробовать поразрабатывать". Есть задача, есть конкретное оборудование, это оборудование на борту содержит 256Мб оперативы. Зачем мне пробовать делать то же самое на STM32? Была бы задача сделать это на STM32, был бы выбран другой язык и инструменты (а в нашей конторе и другой программист, который именно на stm специализируется, ибо специфика разработки под stm подразумевает более комплексное знание схемотехники и физики процессов). Не спорю что можно ту же задачу решить и за меньшее кол-во Мб оперативной памяти, меньшее кол-во Гц процессора и тд, но в нашем конкретном случае стоимость трудозатрат будет выше чем выигрыш от выбора более дешёвого железа.


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

Sign up to leave a comment.

Articles

Change theme settings