Pull to refresh
4
0.1
Сергей @gres_84

C++ Developer

Send message

C++26 — встреча ISO в Хагенберге

Level of difficultyMedium
Reading time8 min
Views21K
В середине февраля в Хагенберге состоялась встреча международного комитета по стандартизации языка программирования C++.



В этот раз прорабатывались следующие большие темы:
  • std::hive
  • Constexpr, ещё больше constexpr
  • Безопасность, контракты, hardening, профили, UB и std::launder
  • Relocate
  • #embed

Об этом и других новинках расскажу в посте

Game++. Juggling STL algorithms

Level of difficultyEasy
Reading time29 min
Views4.6K

Мы все пишем циклы, в каждом софте, в каждой игре они будут. Вы не можете обойтись без них. Скажете, что делает этот код?

stl::vector numbers = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : numbers) {
sum += num;
}

Конечно, это просто: код суммирует элементы массива. Похожую задачу про суммирование или другую операцию над массивом мой лид даёт на собесах :) Люди смотрят с удивлением, а потом большинство пишут, вот то, что было выше. И тут три вещи - человек либо поленился прочитать про STL алгоритмы, либо не доверяет нам и знает про них, но думает что не поймем мы, либо знает, но не понимает зачем показываеть эти знания, почему? вопрос оставим открытым. Этот пример с циклом - простейший алгоритм.

Алгоритмы STL — это настоящий швейцарский нож для разработчика. Они не просто помогают писать код, а делают его чище, понятнее и надежнее. В проектах с большими кодовыми базами, где легаси код не всегда стабилен и удобен для поддержки, это особенно важно. Каждый, кто писал циклы вручную, сталкивался с ошибками: вылезли за границы массива, забыли обработать пустой контейнер, сделали лишнее копирование. STL-алгоритмы избавляют от многих проблем, позволяя выразить мысли кратко и четко. Вместо простыней кода с индексами — несколько строк с понятным смыслом. Так что, если вы еще не знакомы со стандартными алгоритмами, самое время это исправить. Это один из тех инструментов, которые однажды освоив, уже невозможно забыть, это как езда на велосипеде, хорошем промышленном велике, за авторством Кнута или Саттера - надежном и с серийным номером.

Читать далее

Game++. Dancing with allocators

Level of difficultyEasy
Reading time34 min
Views12K

C и C++ не имеют встроенной сборки мусора, поэтому разработчик сам решает, как и когда выделять и освобождать память. Мы, конечно, можем покивать в сторону STL, сокрытия аллокаций в контейнерах, но от этого они никуда не денутся. Просто если раньше приходилось думать про выделенный кусок памяти, понимать, как он скажется на времени фрейма, помнить, что его надо удалить (а может, не надо и стоит оставить на следующий фрейм), то теперь всё заворачивается в сахарные контейнеры и разработку в стиле STL-blin-vse-sterpit. STL-то может и стерпит, и даже как-то будет ворочаться, однако не стоит полагаться исключительно на системный аллокатор, бездумно вызывая new или malloc для каждого запроса памяти. Вы ведь понимаете, что std::vector посреди цикла или горячей функции — это плохая идея?

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

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

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

Ребята из HFT, Database, Automotive и Embedded-систем наверняка могут рассказать немало интересных историй про оптимизацию new/delete. Давайте я расскажу немного про разные аллокаторы в играх?

Аллокатор аллокатору аллокации аллоцировал

Game++. Cooking vectors

Level of difficultyEasy
Reading time12 min
Views6.5K

В разработке игр динамические и статические массивы являются основным инструментом при работе с набором объектов, буду дальше называть их vector. Вы можете подумать про разные map, set, и другие ускоряющие структуры, но их тоже предпочитают делать поверх векторов. Почему так? Вектора просты для понимания, удобны для большого числа задач, особенно там, где объём данных заранее неизвестен или примерно известен. Но как вы понимаете, за все надо платить, и расплачиваться приходится производительностью, которой, как обычно, всегда не хватает. Так что, использование динамических массивов имеет свои ограничения и особенности.

Читать далее

Game++. String interning

Level of difficultyEasy
Reading time9 min
Views8.4K

«String interning», иногда это называют «пулом строк» — это оптимизация (https://en.wikipedia.org/wiki/String_interning), при которой хранится только одна копия строки, независимо от того, сколько раз программа ссылается на нее. Среди других оптимизаций по работе со строками (SWAR, SIMD-cтроки, immutable strings, StrHash, Rope string, и немного других), часть которых была описана тут, она считается одной из самых полезных оптимизаций в игровых движках, есть правда небольшие недостатки у этого подхода, но экономия памяти и скорость работы при правильной подготовке ресурсов и работе с лихвой их перекрывают.

Вы 100% когда-нибудь писали одну и ту же строку несколько раз в одной программе. Например:pcstr color = "black"; А позже в коде пришлось написать: strcmp(color, "black");Как видите, строковый литерал "black" встречается несколько раз. Означает ли это, что программа содержит две копии строки "black"? Более того, означает ли это, что в оперативную память загружаются две копии этой строки? На оба вопроса ответ — зависит от компилятора и вендора. Благодаря некоторым оптимизациям в сlang (Sony) и GCC, каждая строка-литерал хранится в программе только в одном экземпляре, и, следовательно, только одна копия загружается в оперативную память, поэтому иногда cтановятся возможными разные фокусы.

Просто не копируй это...

Game++. run, thread, run…

Level of difficultyEasy
Reading time33 min
Views6.2K

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

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

За кажущейся простотой скрывается множество граблей и ловушек: взаимные блокировки (deadlock), «голодание» потоков, асинхронные ошибки. Это похоже на попытку дирижировать оркестром, где музыканты игнорируют ритм. Проще говоря, любые действия над данными могут привести к проблемам, и чтобы этого не происходило, операции над данными должны быть атомарными, это решается вводом в код примитивов синхронизации, вроде мьютексов, семафоров, спинлоков.

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

Читать далее

Простейшие алгоритмы сжатия: RLE и LZ77

Reading time9 min
Views148K
Давным-давно, когда я был ещё наивным школьником, мне вдруг стало жутко любопытно: а каким же волшебным образом данные в архивах занимают меньше места? Оседлав свой верный диалап, я начал бороздить просторы Интернетов в поисках ответа, и нашёл множество статей с довольно подробным изложением интересующей меня информации. Но ни одна из них тогда не показалась мне простой для понимания — листинги кода казались китайской грамотой, а попытки понять необычную терминологию и разнообразные формулы не увенчивались успехом.

Поэтому целью данной статьи является дать представление о простейших алгоритмах сжатия тем, кому знания и опыт пока ещё не позволяют сходу понимать более профессиональную литературу, или же чей профиль и вовсе далёк от подобной тематики. Т.е. я «на пальцах» расскажу об одних из простейших алгоритмах и приведу примеры их реализации без километровых листингов кода.
Читать дальше →

Спинлок в современном C++ с применением атомиков, барьеров памяти и экспоненциальной выдержкой

Reading time9 min
Views4.6K
Эта статья послужит вам быстрым, но глубоким введением в низкоуровневую конкурентность.

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

В этой статье мы реализуем наш собственный упрощённый спинлок с экспоненциальной выдержкой. Для начала обсудим базовую идею, на которой основан спинлок — проблему активного ожидания. Затем разберём, что представляет собой экспоненциальная выдержка и обсудим, как повысить эффективность спинлоков. Затем поговорим об атомиках и о том, для чего они используются. После этого объясним, что представляют собой барьеры памяти, если они работают в тандеме. Далее рассмотрим образец реализации спинлока с экспоненциальной выдержкой, разберём достоинства и недостатки такого подхода. Наконец, напишем тестовую программу, которая поможет нам убедиться, что всё работает как надо. Начнём!
Читать дальше →

inplace_vector: новый контейнер C++26

Level of difficultyMedium
Reading time5 min
Views5.5K

Вы когда-нибудь мечтали о динамически расширяемом последовательном контейнере с фиксированной емкостью, хранящем свои элементы на стеке? Комитет по стандартизации C++ исполняет желания! Теперь вам не нужно обращаться к Boost.Container за boost::container::static_vector. Встречайте, std::inplace_vector (P0843), принятый в C++26!

Читать далее

Range-v3 в C++

Reading time4 min
Views5.2K

Привет, Хабр!

В этой статье рассмотрим Range-v3 — библиотеку, которая изменила подход к обработке последовательностей в C++ и стала основой для std::ranges в C++20.

Range-v3 — это библиотека, расширяющая стандартную библиотеку C++ возможностью работать с диапазонами вместо begin()/end(). В основе идеи лежат три концепции.

Читать далее

А в чем проблема работать с файлами?

Level of difficultyMedium
Reading time53 min
Views37K

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

Меня увлекла тема отказоустойчивости, а конкретно - отказоустойчивой работы с файлами. В этой статье я попытался соединить все полученные знания:

Кто участвует в процессе записи

Ошибки, которые могут произойти

Что от нас зависит, а что нет

И самое главное - как это этого защититься

Читать далее

Глия: как самые неизученные клетки нервной системы меняют нейронауку

Level of difficultyHard
Reading time13 min
Views3.4K

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

Почему тема глиальных клеток очень популярна именно сейчас, какие виды глии существуют и за что они отвечают, рассказывает научный журналист и главный редактор портала «Нейроновости», член научного комитета премии «Вызов» Алексей Паевский. Специально для нас он кратко изложил историю изучения глии и поделился работами, которые меняют представления о глиальных клетках в нейронауке. Предупреждаем: будет сложно (но интересно).

Читать далее

Сборка проектов Си и Си++: от простого к сложному. Часть I. Библиотеки

Level of difficultyMedium
Reading time12 min
Views24K

Каждый раз, в течение многих лет, собирая пилотную версию мизерного проекта или простой утилиты, мне кажется, что уж в этот раз точно обойдусь обычным скриптом для сборки, и никакие сборщики проекта мне не понадобятся. Но суровая реальность приводит меня в чувство уже в течение первых нескольких минут работы. Сначала оказывается, что до невозможности простая программка нуждается в JSON-парсере, HTTP-запросах CURL и прочих библиотеках. А по мере возбуждения хотелок эти все зависимости нарастают как снежный ком. И все мечты быстро скомпилировать страничку кода встречают на каждом шаге всё новые и новые проблемы.

Вот сегодня и расскажу о том, какие бывают способы борьбы с зависимостями и сборки проекта из множества файлов на Си++. Заодно те, кто не любят Си++, смогут порадоваться «прелестям» этого процесса. И хоть тема очень важная для программистов, но я обратил внимание, что даже многолетний опыт не гарантирует понимания этих процессов. Но сразу предупреждаю — история длинная даже с учетом всех попыток не убегать на смежные темы.
Читать дальше →

Путеводитель C++ программиста по неопределённому поведению

Level of difficultyHard
Reading time3 min
Views13K

Путеводитель C\+\+\ программиста по неопределённому поведению


Вашему вниманию предлагается полный список разделов электронной книги (12 из 11 :)), посвящённой неопределённому поведению. Книга не является учебным пособием и рассчитана на тех, кто уже хорошо знаком с программированием на C++. Это своего рода путеводитель C++ программиста по неопределённому поведению, причём по самым его тайным и экзотическим местам. Автор книги — Дмитрий Свиридкин, редактор — Андрей Карпов.

Читать дальше →

Хронология зарубежной научной фантастики

Level of difficultyEasy
Reading time28 min
Views25K

Опубликованный хронологический справочник содержит зарубежные литературные произведения научной фантастики, которые литературоведы и литературные критики относят к классике жанра. Хронология охватывает период со 160 года до 1 января 2025 года.

Читать далее

Кэш. Теория кэширования. Устройство и разновидности кэша

Level of difficultyEasy
Reading time7 min
Views17K

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

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

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

Стать гуру кэша

System Design для начинающих: всё, что вам нужно. Часть 1

Level of difficultyEasy
Reading time12 min
Views66K

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

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

Читать далее

Сложно о простом. Как работает интернет. Часть 1. Что такое коммутатор, маршрутизатор и примеры работы простых сетей

Level of difficultyEasy
Reading time14 min
Views127K

Приветствую, коллеги! Меня зовут @ProstoKirReal. Мне бы хотелось с вами обсудить как работает интернет от кабелей на витой паре, соединяющие простые локальные сети до подводных коммуникационных кабелей соединяющие между собой континенты и основные операторские сети.

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

Читать далее

Сравнение Bash и Python при написании скриптов в Linux

Level of difficultyMedium
Reading time24 min
Views35K

Sh (от shell) является обязательным командным интерпретатором для UNIX‑совместимых систем по стандарту POSIX. Однако по возможностям он ограничен, поэтому зачастую вместо него используются более богатые возможностями командные интепретаторы, такие как Bash или Ksh. Ksh обычно используется в операционных системах семейства BSD, в то время как Bash — в операционных системах семейства Linux. Командные интерпретаторы облегчают решение мелких задач, связанных с работой с процессами и файловой системой. В данной статье будут рассматриваться операционные системы Linux, поэтому речь пойдёт о Bash.

Python, в свою очередь, является полноценным интерпретируемым языком программирования, и он также нередко используется для написания скриптов или решения мелких прикладных задач при работе с операционной системой. Современную UNIX‑подобную систему сложно представить как без Sh, так и без Python, если только это не устройство с минималистичной ОС вроде маршрутизатора. Например, в Ubuntu Oracular пакет python3 удалить не получится хотя бы потому, что от него зависит пакет grub‑common, от которого, в свою очередь зависят пакеты grub2-common и, соответственно, grub‑pc, то есть непосредственно загрузчик операционной системы. Таким образом, Python 3 можно смело использовать как замену Bash в случае необходимости.

Читать далее

Ещё раз про алгоритм сжатия Хаффмана

Level of difficultyHard
Reading time21 min
Views21K

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

Читать далее

Information

Rating
3,518-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity