Контроль бинарного кода на проекте C++
От: cppguard  
Дата: 04.05.21 23:17
Оценка: 3 (1) +2
Часто можно слышать, что С++ выбирают за быстроту при большом многообразии выразительных средств. И вот читая очередную статью про противоестественную ошибку на пустом месте у меня вдруг возник вопрос: а как вообще в более-менее крупных проектах выполняется контроль сгенерированного кода? Вот допустим описал программист нетривиальный конструктор у класса, который должен по всем правилам избегать двойного копирования (copy elision, move semantics, etc.), но запутался в l-value и r-value ссылках, в итоге код получился неоптимальным. Но если судить по тем статьям, что описывают такие случаи, то проблема обнаруживается или когда бинарный код начинает неимоверно жиреть, или когда производительность заметно падает в узких местах. Получается, что чтобы пользоваться всеми преимуществами С++, нужно или каждый метод при каждом изменении прогонять через godbolt и глазами убеждаться, что компилятор понял идею автора правильно, или обложиться тестами производительности по самое не хочу. Или есть какой-то другой метод? Вариант "мы нанимаем только экспертов С++" я не рассматриваю, потому что вся история ЭВМ построена на уменьшении влияния человеческого фактора на процесс построения корректных и эффективных программ. И вот ещё одно интересное наблюдение: многие именитые фигуры из мира С++ вроде Герба Саттера как таковой рабочий код не пишут, они могут обсуждать новый стандарт, разные скользкие моменты, идиоматичность разных конструкций и вообще что-угодно, кроме написания production-ready кода. А один из самых известных авторов и проповедников С++, Скотт Мейерс, вообще ни разу в жизни не работал программистом, если верить ему самому. Только вдумайтесь — человек, который консультирует в области использования С++, сам никогда не писал на нём!

Данная тема — не попытка развязать сотый holly war на тему, просто мне всегда было интересно, как пользоваться С++ правильно. На тех, проектах, где я работал, ситуация всегда была в духе "хотели как лучше, а получились как всегда" в том смысле, что кодовая база росла, программисты была разного качества, кто-то писал идиоматичных С++, кто-то на Си с конструкторами, всё это было приправлено сегфолтами и всё в таком духе.
Re: Контроль бинарного кода на проекте C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 05.05.21 03:32
Оценка: +2
Здравствуйте, cppguard, Вы писали:

C>Данная тема — не попытка развязать сотый holly war на тему, просто мне всегда было интересно, как пользоваться С++ правильно. На тех, проектах, где я работал, ситуация всегда была в духе "хотели как лучше, а получились как всегда" в том смысле, что кодовая база росла, программисты была разного качества, кто-то писал идиоматичных С++, кто-то на Си с конструкторами, всё это было приправлено сегфолтами и всё в таком духе.


Смотря что за проект. Если результат не сильно критичен по скорости, то ляпы могут закрадываться. Если критичен, то пишутся тесты на корректность результата и скорость работы. Запустили, тесты прошло, медленнее не стало — ок. Если стало медленнее, то уже разбираться.
Re: Контроль бинарного кода на проекте C++
От: Lucky Cat  
Дата: 05.05.21 05:05
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Часто можно слышать, что С++ выбирают за быстроту при большом многообразии выразительных средств. И вот читая очередную статью про противоестественную ошибку на пустом месте у меня вдруг возник вопрос: а как вообще в более-менее крупных проектах выполняется контроль сгенерированного кода? Вот допустим описал программист нетривиальный конструктор у класса, который должен по всем правилам избегать двойного копирования (copy elision, move semantics, etc.), но запутался в l-value и r-value ссылках, в итоге код получился неоптимальным. Но если судить по тем статьям, что описывают такие случаи, то проблема обнаруживается или когда бинарный код начинает неимоверно жиреть, или когда производительность заметно падает в узких местах. Получается, что чтобы пользоваться всеми преимуществами С++, нужно или каждый метод при каждом изменении прогонять через godbolt и глазами убеждаться, что компилятор понял идею автора правильно, или обложиться тестами производительности по самое не хочу. Или есть какой-то другой метод? Вариант "мы нанимаем только экспертов С++" я не рассматриваю, потому что вся история ЭВМ построена на уменьшении влияния человеческого фактора на процесс построения корректных и эффективных программ. И вот ещё одно интересное наблюдение: многие именитые фигуры из мира С++ вроде Герба Саттера как таковой рабочий код не пишут, они могут обсуждать новый стандарт, разные скользкие моменты, идиоматичность разных конструкций и вообще что-угодно, кроме написания production-ready кода. А один из самых известных авторов и проповедников С++, Скотт Мейерс, вообще ни разу в жизни не работал программистом, если верить ему самому. Только вдумайтесь — человек, который консультирует в области использования С++, сам никогда не писал на нём!


C>Данная тема — не попытка развязать сотый holly war на тему, просто мне всегда было интересно, как пользоваться С++ правильно. На тех, проектах, где я работал, ситуация всегда была в духе "хотели как лучше, а получились как всегда" в том смысле, что кодовая база росла, программисты была разного качества, кто-то писал идиоматичных С++, кто-то на Си с конструкторами, всё это было приправлено сегфолтами и всё в таком духе.



Все вышеозначенные саттеры и мейерсы пишут о языке, а упомянутые проблемы это не проблемы языка, а проблемы архитектуры скорее, проблемы стиля, проблемы организации проекта.
Те же самые проблемы могли быть с любым языком
Re: Контроль бинарного кода на проекте C++
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.05.21 06:30
Оценка:
Здравствуйте, cppguard, Вы писали:

C>как вообще в более-менее крупных проектах выполняется контроль сгенерированного кода? Вот допустим описал программист нетривиальный конструктор у класса, который должен по всем правилам избегать двойного копирования (copy elision, move semantics, etc.), но запутался в l-value и r-value ссылках, в итоге код получился неоптимальным.


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

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


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

C>Получается, что чтобы пользоваться всеми преимуществами С++, нужно или каждый метод при каждом изменении прогонять через godbolt и глазами убеждаться, что компилятор понял идею автора правильно, или обложиться тестами производительности по самое не хочу. Или есть какой-то другой метод?


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

C>Вариант "мы нанимаем только экспертов С++"


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

C>многие именитые фигуры из мира С++ вроде Герба Саттера как таковой рабочий код не пишут


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

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


Они все исходят из того, что достаточно устаканить форму, свойства и методы соединения отдельных элементарных блоков, а дальше из этих блоков любой сможет собрать конструкцию любой сложности. Именно так и происходит в схемотехнике, но там ограничения по месту/объему, скорости и потреблению энергии гораздо строже. Грубо говоря, нынешняя технология софтописания на словах напоминает разработку красивой печатной платы на микросхемах, с автоматизированной разводкой и монтажом, а результаты больше напоминают ЭВМ 50-60-х, состоящие из множества шкафов, набитых блоками и жгутами проводов, к которым прилагался инженерный отдел для сопровождения и ремонта.





А один из самых известных авторов и проповедников С++, Скотт Мейерс, вообще ни разу в жизни не работал программистом, если верить ему самому. Только вдумайтесь — человек, который консультирует в области использования С++, сам никогда не писал на нём!

C>Данная тема — не попытка развязать сотый holly war на тему, просто мне всегда было интересно, как пользоваться С++ правильно. На тех, проектах, где я работал, ситуация всегда была в духе "хотели как лучше, а получились как всегда" в том смысле, что кодовая база росла, программисты была разного качества, кто-то писал идиоматичных С++, кто-то на Си с конструкторами, всё это было приправлено сегфолтами и всё в таком духе.
Re[2]: Контроль бинарного кода на проекте C++
От: cppguard  
Дата: 05.05.21 07:49
Оценка: :))
Здравствуйте, Nuzhny, Вы писали:

N>Смотря что за проект. Если результат не сильно критичен по скорости, то ляпы могут закрадываться. Если критичен, то пишутся тесты на корректность результата и скорость работы. Запустили, тесты прошло, медленнее не стало — ок. Если стало медленнее, то уже разбираться.


Почему бы тогда не писать на Java или Haskell? Скорость та же, вероятность ошибиться — меньше.
Re[2]: Контроль бинарного кода на проекте C++
От: Skorodum Россия  
Дата: 05.05.21 07:52
Оценка: +2
Здравствуйте, Lucky Cat, Вы писали:

LC>Те же самые проблемы могли быть с любым языком

Не, не с любым, плюсы в этом плане сильно выделяются. На всяких питонах узкие куда более очевидны.
Re[2]: Контроль бинарного кода на проекте C++
От: cppguard  
Дата: 05.05.21 08:22
Оценка:
Здравствуйте, Lucky Cat, Вы писали:

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

LC>Те же самые проблемы могли быть с любым языком

В том-то и дело, что не с любым! Перед тем, как написать пост, я пытался вспомнить случаи из практики, связанные с Python или Java, и не смог. Лишь могу вспомнить баг Java на x86, когда запись long не была атомарной, и в случае состояния гонки простая запись в переменную могла создать там мусор.
Re: Контроль бинарного кода на проекте C++
От: a7d3  
Дата: 05.05.21 08:40
Оценка: +1
Здравствуйте, cppguard, Вы писали:

C>Данная тема — не попытка развязать сотый holly war на тему, просто мне всегда было интересно, как пользоваться С++ правильно. На тех, проектах, где я работал, ситуация всегда была в духе "хотели как лучше, а получились как всегда" в том смысле, что кодовая база росла, программисты была разного качества, кто-то писал идиоматичных С++, кто-то на Си с конструкторами, всё это было приправлено сегфолтами и всё в таком духе.


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

В общем, чего-то не в тех командах, не в тех проектах довелось работать. Вещь настолько банальная, как и юнит-тесты. Можно сказать, вопрос на уровне того, как лет 15 назад не все пользовались баг-треккингом и VCS, да спрашивали о том надо ли, а как и зачем.
Re[3]: Контроль бинарного кода на проекте C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 05.05.21 08:50
Оценка:
Здравствуйте, cppguard, Вы писали:

N>>Смотря что за проект. Если результат не сильно критичен по скорости, то ляпы могут закрадываться. Если критичен, то пишутся тесты на корректность результата и скорость работы. Запустили, тесты прошло, медленнее не стало — ок. Если стало медленнее, то уже разбираться.

C>Почему бы тогда не писать на Java или Haskell? Скорость та же, вероятность ошибиться — меньше.

Потому что исторически моя предметная область живёт на С++. Может быть, часть переедет на Rust, но пока к этому особых предпосылок нет.
Re[3]: Контроль бинарного кода на проекте C++
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.05.21 09:03
Оценка: +1 :)
Здравствуйте, Skorodum, Вы писали:

LC>>Те же самые проблемы могли быть с любым языком


S>Не, не с любым, плюсы в этом плане сильно выделяются.


Когда-то плюсы тоже не выделялись. Сильно выделяться они стали только после того, как нормой программирования на плюсах стало извращенное и неумеренное использование сложношаблонных конструкций, отслеживать которые гораздо труднее, чем макросы того же уровня сложности.
Re[4]: Контроль бинарного кода на проекте C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 05.05.21 09:41
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


Не только. Например, у меня программа использует код на CUDA или что-то с тяжёлыми вычислениями на CPU. Что мне делать? Какие инструкции можно использовать? Получается, что я ставлю CUDA компилятору флаги, чтобы код собирался под пяток последних архитертур видеокарты — код распухает. Также я подключаю библиотеки от Nvidia, которые также собраны под несколько архитектур — они размером в сотни мегабайт. Аналогично для CPU: у меня серия бинарников, собранных для SSE, AVX, AVX2... Далее у меня Intel MKL, который тоже содержит в себе реализацию одних и тех же функций, оптимизированных под разные архитектуры — тоже сотни мегабайт.
Вот это всё хозяйство включается в установщик и кажется: что так много?!! Да, можно сократить объём кода на порядок, но он либо будет работать не оптимально на современном железе, либо вообще не будет работать у кучи пользователей. Теперь можно подумать, что важнее пользователю экономить память или скорость работы приложения (это ещё и батарейка ноута, его нагрев, экономия ядер на сервере)? По факту оказывается, что для экологии логичней экономить такты, а не объёмы.
Re[5]: Контроль бинарного кода на проекте C++
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.05.21 10:30
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Например, у меня программа использует код на CUDA или что-то с тяжёлыми вычислениями на CPU. Что мне делать? Какие инструкции можно использовать?


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

N>Получается, что я ставлю CUDA компилятору флаги, чтобы код собирался под пяток последних архитертур видеокарты — код распухает.


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

N>Также я подключаю библиотеки от Nvidia, которые также собраны под несколько архитектур — они размером в сотни мегабайт. Аналогично для CPU: у меня серия бинарников, собранных для SSE, AVX, AVX2... Далее у меня Intel MKL, который тоже содержит в себе реализацию одних и тех же функций, оптимизированных под разные архитектуры — тоже сотни мегабайт.


А вот это уже интересно. Что там может занимать сотни мегабайт, кроме каких-нибудь таблиц для оптимизации вычислений?
Re: Контроль бинарного кода на проекте C++
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 05.05.21 10:48
Оценка: 6 (2)
Здравствуйте, cppguard, Вы писали:

C> И вот читая очередную статью про противоестественную ошибку на пустом месте


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

C> у меня вдруг возник вопрос: а как вообще в более-менее крупных проектах выполняется контроль сгенерированного кода?


Это не надо. У тебя есть два три типа проектов:

1) 99% это проекты где тебе не очень важно что там сгенерирует компилятор. Ты знаешь что двоичный код C++ достаточно эффективен и тебе этого хватает. В таком случае ты включаешь динамические (sanitizer-ы) и статические (clang-tidy и компания) анализаторы, пишешь модульные тесты и радуешься тому что у тебя такой классный и не падучий код. Код реально будет очень классным и почти не будет падать по причинам плохого знания C++. Что значит "почти"? Почти значит — ты всё еще можешь устроить гонки, если постараешься, но в каком языке ты не можешь? ааа... правильно, в любом можешь если хорошо постараешься!

2) ты в 0.5% проекторв где важна safety (хрен знает как на русский перевести, ОБЖ короче). Это когда у тебя атомный реактор или критический компонент в самолете или самоходной карете. Ну, ты в жопе, тут ничего иного не скажешь. Если ты вдруг в неё залез, то ты пишешь на Си-с-классами где нельзя кидать исключения, нельзя выделять память динамически и много других "нельзя". Из хороших моментов, тот компилятор что ты исполняешь тебя сразу бьет по рукам за попытку прыжка на месте (а иногда и расстреливает), а статический анализатор (за который ты отвалил дохулиард не-рублей) так же, сцуко, люто бдит. В итоге у тебя код где ты точно знаешь что и почему происходит, но за очень много денег, т.к. твоя производительность упала в 5-10 раз.

3) ты в другой части 0.5% проектов, которые пишут трейдеры. Ну... тут ты прав и godbolt, кажется написанный трейдером, твой лучший друг и советник
Re[6]: Контроль бинарного кода на проекте C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 05.05.21 10:57
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А вот это уже интересно. Что там может занимать сотни мегабайт, кроме каких-нибудь таблиц для оптимизации вычислений?


Я хз. Но сами разработчики MKL рассказывали, что у них множество независимых реализаций одних и тех же функций на своих интрисиках/ассемблере и со своими настройками. Оно всегда было объёмным, но с каждым годом становится всё больше и больше.
Re: Контроль бинарного кода на проекте C++
От: Wawan Россия http://www.wawan.ru/resume
Дата: 05.05.21 18:48
Оценка:
включаю в настройках проекта режим сохранения ассемблерного листинга вместе с исходным с++ кодом
смотрю какой ассемблерный код генерится в интересующих меня местах
гдето меняю с++ код и перекомпиливаю, потом Araxis Merge сравниваю новый ассемберный код со старым, делаю выводы.
Re[2]: Контроль бинарного кода на проекте C++
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.05.21 21:57
Оценка: +1
Здравствуйте, kaa.python, Вы писали:

KP>2) ты в 0.5% проекторв где важна safety (хрен знает как на русский перевести, ОБЖ короче).


Я бы перевел как "надежность".

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


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

Проблема дорогих инструментов в том, что у них три с половиной пользователя, да и те не по своей воле. Сколько бы в их разработку денег не вкладывалось, большая пользовательская база очень важна.
Re: Контроль бинарного кода на проекте C++
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.05.21 22:00
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Часто можно слышать, что С++ выбирают за быстроту при большом многообразии выразительных средств. И вот читая очередную статью про противоестественную ошибку на пустом месте у меня вдруг возник вопрос: а как вообще в более-менее крупных проектах выполняется контроль сгенерированного кода?


Да никак он там не выполняется, по большей части.

Ценность контроля за бинарным выхлопом компилятора очень переоценена. Большая часть кода любой программы исполняется очень редко, и совершенно не важно, сколько ресурсов этот код потребляет, лишь бы укладывался в разумно достижимые.
Re: Контроль бинарного кода на проекте C++
От: reversecode google
Дата: 07.05.21 00:20
Оценка:
C>Часто можно слышать, что С++ выбирают за быстроту при большом многообразии выразительных средств. И вот читая очередную статью про противоестественную ошибку на пустом месте

так там нет ошибки
и в комментах там очень сильно все разжевали
Re: Контроль бинарного кода на проекте C++
От: Quebecois Канада https://www.canada.ca/
Дата: 07.05.21 01:02
Оценка: +1
Здравствуйте, cppguard, Вы писали:

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

А если производительность падает ниже желаемой, то подключается профайлер и все быстро оптимизируется до нужной степени.
Re[7]: Контроль бинарного кода на проекте C++
От: Тёмчик Австралия жж
Дата: 07.05.21 01:34
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Я хз. Но сами разработчики MKL рассказывали, что у них множество независимых реализаций одних и тех же функций на своих интрисиках/ассемблере и со своими настройками. Оно всегда было объёмным, но с каждым годом становится всё больше и больше.


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