Post has shared content
Интереснейший доклад о том, как устроена память "внутри". Обычно в ВУЗах часть этой информации дается на программировании, другая - на операционных системах, а третья - на курсах типа "архитектура ЭВМ". Итак, доклад построен вокруг трех строчек кода:

1) int* ptr = new int;
2) *ptr = 42;
3) delete ptr;

В принципе, все это применимо к любому другому языку программирования. В первой строке мы выделяем динамическую память для хранения целого числа. Во второй - записываем по полученному адресу число 42. В третьей - освобождаем память. Но что же внутри? (ответ дается для архитектуры x86_64, операционной системы Linux и аллокатора jemalloc {один из хороших аналогов стандартному аллокатору}). Ниже краткое содержание доклада с таймингом:

7:40 - оказывается malloc работает по-разному для "маленьких" и "больших" объектов. У нас объект маленький... .

9:30 - оказывается аллокатор поддерживает хитрую структуру данных для быстрого выделения памяти под объекты разных размеров - называется tcache. Для каждого размера есть что-то типа "обоймы" готовых объектов, откуда malloc может что-то "попросить".

11:05 - если же в "обойме" нет свободного объекта - то приходится идти в глобальную кучу и просить область памяти там. Для этого поддерживается глобальный для каждого потока объект управления памятью - Arena. Внутри арены, опять же, поддерживаются различные механизмы для выделения памяти под маленькие и большие объекты. Для маленьких (как у нас) - поддерживается структура данных Slab.

12:50 - показано как slab устроен внутри. Slab - это массив объектов одинакового размера + информация об их использовании. Он может дать свободный объект если таковой есть. При этом устроен так, что минимизируется объем метаданных для объекта. Slab создается несколько, все они хранятся в очереди. Если в Slab нет свободных объектов - создается новый Slab или ищется "свободный" в очереди. При поиске используется эвристика для борьбы с фрагментацией.

18:30 - но как создать новый Slab? - использовать malloc. Рекурсия, но проблем не возникнет, т.к. Slab - большой объект и для него будет использоваться другой механизм выделения памяти. Описывается подсистема управления большими объектами (Extent) - хитрая структура данных и алгоритм.

22:30 - если вдруг при выделении памяти под Slab (или другой большой объект) оказалось, что память процесса кончилась... Обращаемся к операционной системе за новым куском памяти с помощью вызова mmap, который дает процессу дополнительную область памяти.

24:10 - хорошая картинка, показано что мы уже сделали чтобы получить память.

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

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

30:25 - все что описано выше - работает медленно, поэтому используется TLB - кэш над PTE.

32:05 - как работает освобождение памяти (третья строка кода). Проблема - нужно знать сколько памяти было выделено по указателю. Для этого в jemalloc используется структура данных rtree - глобальный объект с информацией об отображении адресов в метаданные аллокатора.

35:30 - рассказано как лучше вернуть память операционной системе и хитрый механизм с эвристикой, используемый в jemalloc.

40:00 - вопросы.

#cplusplus
#видео

https://www.youtube.com/watch?v=i87W3KyZgPw

Post has shared content
Краткое содержание интересного доклада с CoreHard Spring 2018: "Инструменты профайлинга С++ кода":

1:40 что такое профайлинг (профилирование) и какие проблемы с его помощью можно решить.

3:45 классификация профайлеров - тут же обозначается ряд проблем профилировщиков, обсусловленных типом профилирования;

10:00 gprof - консольный профайлер для Linux. Описаны основные недостатки, показано как его использовать;

13:30 gcov - работает также как gprof, но выводит информацию о строках кода (например "сколько раз была выполнена строка");

14:20 gprof2dot - скрипт на Python, который позволяет визуализировать результаты работы не только gprof, но и ряда других профайлеров. Приведены примеры использования;

17:00 gperftools - инструмент для профилирования "вручную". В отличии от gprof умеет профилировать многопоточный код;

19:00 valgrind - фреймворк для эмулирующей профилировки под Linux и MacOS. Содержит множество утилит, а также дополнительные инструменты для визуализации данных:

* cachegrid - для профилирования кэша (информация о кэш-промахах и т.п.);
* callgrid - строит граф вызовов и дает информацию о времени работы функций;
* memcheck и massif - профилирование памяти, дают информацию об утечках и аллокациях соответственно;
* DRD и Helgrid — инструменты для профилирования многопоточных приложений. Позволяют, например, найти взаимоблокировки.

25:40 Heaptrack — позволяет профилировать и визуализировать:

* динамику потребления памяти;
* количество утечек;
* распределение потребления памяти по функциям;
* строить flamegraph потребления ОЗУ (дальше в докладе рассказывается что такое flamegraph и как его читать);

29:05 Intel VTune Amlifier — проприетарный, но бесплатный профилировщик для программ на процессорах Intel (работает только на этих процессорах). Умеет профилировать кэш программ, branch prediction, встроенное GPU. С его помощью можно, например, узнать сколько чего выполнялось на каждом ядре. Красиво визуализирует результаты.

32:10 CodeXL и AMD μProf — аналогичные инструменты для процессоров AMD. Также, XCode + Instruments содержит инструменты для профилирования в MacOS и iOS. SimplePerf — профайлер для Android (встроен в Android Studio начиная с версии 3.1).

37:28 Кратко охарактеризованы другие профайлеры, которые не вошли в доклад. Приведены советы по профилированию (очевидные, но полезные), а также, «полезные ссылки» с комментариями.

Ссылка на видео: https://www.youtube.com/watch?v=V1SN_IuUh7s

#cplusplus
#профилирование
#видео

Post has attachment
Разработка больших сложных проектов невозможна без использования методологий программирования и инструментальных средств, помогающих контролировать качество кода. В первую очередь, это грамотный стандарт кодирования, обзоры кода, юнит-тесты, статические и динамические анализаторы кода. Всё это помогает выявлять дефекты в коде на самых ранних этапах разработки. В этой статье демонстрируются возможности статического анализатора PVS-Studio по выявлению ошибок и потенциальных уязвимостей в коде операционной системы Android. Надеемся, что статья привлечёт внимание читателей к методологии статического анализа кода и они захотят внедрить её в процесс разработки собственных проектов. #android #pvsstudio https://habr.com/company/pvs-studio/blog/418891/

Post has attachment
С 19 по 21 апреля в Санкт-Петербурге прошла конференция С++ Russia 2018. Из года в год организация и проведение становится на уровень выше, что не может не радовать. Спасибо бессменному организатору С++ Russia Сергею Платонову за его вклад в развитие этого направления. https://habr.com/company/pvs-studio/blog/418645/

Post has attachment
7 — 8 апреля сообщество CoreHard провело в Минске восьмую международную конференцию CoreHard Spring 2018, посвященную языку С++ и сопутствующим «хардкорным» технологиям. В конференции участвовали спикеры из ведущих IT-компаний Беларуси, России, Украины, Германии и Голландии. Они рассказали о своем опыте в разработке и тестировании.
Теперь доклады с конференции размещены в свободном доступе на YouTube и все желающие могут познакомиться с ними. Благодарим организаторов конференции.
https://habr.com/company/pvs-studio/blog/414467/

Post has attachment
Не так давно состоялся релиз новой версии свободного графического редактора Krita 4.0. Самое время проверить этот проект с помощью PVS-Studio. https://habrahabr.ru/company/pvs-studio/blog/354120/

Post has shared content
Дополнил пример из предыдущей статьи обнаружением столкновений. Теперь наш ежик не просто ходит а поедает синие точки и останавливается перед деревьями.

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

#qt #gamedev #cplusplus

https://pro-prof.com/forums/topic/qt_collision_detection

Post has shared content
Аннотация и краткое содержание двухчасового доклада о нововведениях в С++17 с конференции С++Russia2016. Докладчик Антон Полухин.

Тайминг с комментариями:
4:30 — оглавление;
1) (синтаксический сахар)
5:20 — автоматическое определение шаблонных параметров классов.
Раньше писали: std::pair<int, double> p(17, 42.0)
Сейчас можно: std::pair p(17, 42.0);
Компилятор сам определит типы шаблонов. Часто это позволяет сократить объем кода;
8:24 — описание некоторых деталей реализации определения параметров шаблонов: проблем с std::array, рассмотрен пример с deduction_guide (мы можем теперь писать такие инструкции для компилятора, которые помогут ему вывести тип шаблона);
11:40 — вопросы по теме.

2) (повышение эффективности)
16:55 std::to_chars и std::from_chars — методы эффективно решают проблему преобразования строки в число и наоборот. На примерах показано насколько сложно правильно и эффективно реализовать эти методы. Вариант с stringstream имеет зависимость от, который весит 1.5Мб и работает неэффективно, т.к. может выделять память во время выполнения. Кроме того, основные проблемы возникают с локалью — она замедляет работу в 10–20 раз. Добавленные в стандарт функции решают проблему без зависимостей от sstream, не работают с локалью, но зато работают в 20–100 раз быстрее.
21:35 — вопросы по теме.

3) (синтаксический сахар, мелочь)
26:00 — std::*_v. В С++11 добавили type_traits — набор структур для метопрограммирования, например std::is_same<T1,T2>, который позволял сравнить 2 типа. В С++14 для проверки писали:
std::is_same<T1,T2>::value
Сейчас появилась более короткая запись:
std::is_same_v<T1,T2>

4) (важно)
27:40 — std::variant — шаблонный класс, который принимает любое количество шаблонных параметров и фактически представляет собой union, который "помнит" какое значение было записано последним. Например std::variant v; Переменная v хранит или int, или строку или double.
29:00 реализация в std, в отличии от boost никогда не выделяет память под собственные нужды;
30:45 — примеры использования std::variant — продемонстрировано как помещать в него данные, как извлекать и в каких случаях можно получить ошибку).
34:40 — вопросы по теме.

5) (синтаксический сахар, мелочь)
44:10 — std::in_place. Функция встречалась в примерах к std::variant. Отмечаются возможные проблемы с ее поддержкой в IDE.

6) (перерыв, на котором рассказывается как происходит заседание коммитета стандартизации).
46:40 — как устроены рабочие группы, чем они занимаются (оказывается там есть рабочая группа для вопросов GameDev и вообще много всего...).
49:40 — шуточный рассказ о том как вы должны действовать чтобы ваши предложения приняли в стандарт языка.

7) (синтаксический сахар)
1:00:50 инициализация в условных выражениях. В С++17 стало можно писать так:
if (auto state = get_state(); is_good(state)) {}
Т.е. инициализировать переменную в конструкциях if и switch подобно тому, как раньше это делалось в for.
1:01:40 — вопросы по теме.

8) (синтаксический сахар, мелочь)
1:06:00 — std::size. Добавлен метод, который вернет количество элементов. При этом если он вызван для контейнера, у которого есть метод size — то этот метод будет вызван. Но эта функция работает и для массивов (избавляет нас от необходимости писать страшный код с шаблонами).

9) (важно, многопоточные алгоритмы)
1:07:23 — все алгоритмы из std::algorithms начиная с С++17 получили многопоточную версию. Такая версия первым аргументом принимает execution policy (стратегию выполнения), с помощью которой можно настроить поведение. Поведение может быть последовательным, параллельным и параллельным–векторизованным. Важно, что параллельные алгоритмы с последовательной стратегией отличаются от последовательных в части обработки исключений.
1:10:10 — вопросы по теме (интересно, что в зависимости от реализации библиотеки внутри может использоваться даже OpenMP).

10) (важно, синтаксический сахар)
1:12:25 — позволяет разбить на части любую структуру (в т.ч. std::pair) с публичными полями. Использовать стоит для улучшения читабельности кода. Например:
auto [ok, info] = get_info();
if (ok) throw safe_info_exception();
return info;
В С++14 вместо ok и info использовались бы.first и.second объекта std::pair.
Важно, что связывание создает не ссылки на элементы структуры, а алиасы (специальный тип объекта, с которым работает компилятор). Это работает эффективнее ссылки (доступ быстрее). Кроме того, алиасы работают для битовых полей, а ссылки — не могут этого.

11) (важно, синтаксический сахар)
1:32:05 — std::visit и constexr lambda. Рассматривается пример, где новая функция std::visit используется для привязывания к std::variant на этапе компиляции функций–обработчиков (для хранимых типов). Во время выполнения в объекте variant появляется значение некоторого типа и для него выполяется функция. В этом же примере используются constexr lambda–функции (раньше их просто небыло).

12) (синтаксический сахар, мелочь)
1:35:45 — if constexpr — оператор if, который выполнится на этапе компиляции. Полезная штука для метопрограммирования.

13) (важно, повышение эффективности)
1:40:44 — splicing maps and sets. Добавлена функция extract, которая позволяет виртуально удалить узел из древовидных структур типа set/map. Физически узел при этом не удаляется, экономим на выделении памяти.

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

Узел можно изменить и вернуть в дерево (также без лишних копирований), а можно вставить в другую древовидную структуру.

(дальше коротко, т.к. у докладчика кончилось время)

14) (синтаксический сахар)
1:52:30 — про string_view, которая позволяет унифицированно заменить различные представления строк (std::string, char* с нуль–терминатором и char* с длиной строки).

15) (важно)
1:56:30 — std::filesystem. Почти boost::filesystem. В качестве примера использования рассматривается код утилиты, аналогичной системной ls.

16) (прочее)
1:59:23 — некоторые функции теперь не рекомендованы к использованию (помечены deprecated).
Добавлен синтаксис template struct...
Добавлен синтаксис [*this](){... }
Добавлено много математических функций
Добавлены вложенные пространства имен — namespace foo::bar::test {}

#cplusplus
#видео

https://www.youtube.com/watch?v=GK9gtIrJaBk

Post has attachment
We are happy to inform you that CppDepend v2018.1 has been released.

For more details: https://www.cppdepend.com/cppdependv2018
CppDepend is free for Open source contributors: https://www.cppdepend.com/CppDependForOSS

CppDepend v2018.1 comes with these important updates:

- CERT and HICPP standard checks,
- More rules to check your modern C++ codebase(C++11,C++14,C++17): More than 20 modernization detections
- Clang-tidy tool embedded for more issues detection
- Analysis of the CMake format specification: CppDepend analyzes now out of the box the CMake Compilation Database Format Specification.
- C++ Core Guidelines support
- New rules related to the performance and the readability issues

#codequality #staticanalysis #cpp #c

Post has attachment
Предлагаем вашему вниманию цикл статей, посвященных рекомендациям по написанию качественного кода на примере ошибок, найденных в проекте Chromium. Это первая часть, которая будет посвящена функции memset. https://www.viva64.com/ru/b/0553/
Wait while more posts are being loaded