Технологии и разработка СУБД
Лекция 5. Практический C/C++
Анастасия Лубенникова
Александр Алексеев
Лекция 5
Autotools & CMake
Пример CMakeList.txt
Git Submodules
$ git submodule add https://github.com/glfw/glfw glfw
$ git submodule init
$ git submodule update
(И да, Subversion / Mercurial по факту мертвы, не тратьте на них время)
make vs ninja
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release -G Ninja ..
$ ninja -j4
$ ninja test
Форматирование кода: CMakeLists.txt
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
add_custom_target(format
COMMAND clang-format --style=file -i ${ALL_SOURCE_FILES} )
Форматирование кода: .clang-format
Language: Cpp
AlignEscapedNewlinesLeft: true
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
...
Основные виды тестирования
Test-Driven Development (TDD)
Особая крайность, когда сначала пишутся тесты, а потом код. Хорошая практика, как минимум, потому что вы уверены, что тест не проходит, если кода нет или он неправильный. Также вы уверены, что код большей частью покрыт тестами.
Тестирование: CMakeLists.txt
enable_testing()
add_test(NAME python_tests
COMMAND py.test -s -v ${CMAKE_SOURCE_DIR}/tests/run.py)
Тестирование: PyTest
class TestBasic:
# ...
def test_index(self):
self.log.debug("Running test_index")
res = requests.get('http://localhost:{}/'.format(PORT))
assert(res.status_code == 200)
Property-based тесты: пример
@pytest.mark.randomize(num=int, min_num=3,
max_num=1000, ncalls=100)
def test_quickcheck(self, num):
result = list(fibgen(num))
assert(result[0] < result[-1])
assert(len(result) == num)
Property-based тесты: зачем?
Code Coverage: CMakeLists.txt
option(USE_GCOV "Create a GCov-enabled build." OFF)
if (USE_GCOV)
set(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
set(GCC_COVERAGE_LINK_FLAGS "-lgcov")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )
Code Coverage: генерация отчета
cmake -DUSE_GCOV=ON ..
make
make test
lcov --directory . --capture --output-file summary.info
mkdir report
genhtml -o ./report summary.info
Code Coverage: результат
Code Coverage: построчно
Статический анализ кода
Статический анализ: Clang Static Analyzer
$ cmake -DCMAKE_C_COMPILER=`which clang` \
-DCMAKE_CXX_COMPILER=`which clang++` -G Ninja ..
$ ninja clean
$ mkdir -p ~/temp/report
$ scan-build -o ~/temp/report ninja -j4
Статический анализ: пример отчета
Valgrind: зачем?
Valgrind: пример использования
$ gcc -O0 -g vgcheck.c -o vgcheck
$ valgrind --leak-check=full --track-origins=yes ./vgcheck
Valgrind: пример отчета
==2205== Conditional jump or move depends on uninitialised value(s)
==2205== at 0x4E800EE: vfprintf (in /usr/lib/libc-2.25.so)
==2205== by 0x4E87EA5: printf (in /usr/lib/libc-2.25.so)
==2205== by 0x4005CA: run_test (vgcheck.c:10)
==2205== by 0x4005F4: main (vgcheck.c:18)
==2205== Uninitialised value was created by a stack allocation
==2205== at 0x400586: run_test (vgcheck.c:6)
Valgrind: что в нем еще есть
Heaptrack: профилировщик памяти
$ heaptrack ./test_rbtree
# или: heaptrack -p PID
$ heaptrack_print --print-leaks \
--print-histogram histogram.data \
--print-massif massif.data \
--print-flamegraph flamegraph.data \
--file ./heaptrack.test_rbtree.22023.gz > report.txt
Heaptrack: визуализация собранных данных
$ massif-visualizer massif.data
Как не нужно делать бенчмарки
perf top
$ sudo perf top -p 12345
perf record
$ sudo perf record -p 12345 -F 99 -g
$ git clone https://github.com/brendangregg/FlameGraph
$ sudo perf script | \
./FlameGraph/stackcollapse-perf.pl > out.perf-folded
$ ./FlameGraph/flamegraph.pl out.perf-folded > perf.svg
Получаем флеймграф
Один полезный прием с GDB
$ gdb --batch --command=gdb.script -p 12345
… где в gdb.script написано просто:
bt
Иногда позволяет найти, где процесс долго висит в блокировке.
DTrace и компания
Инструменты трассировки ядра операционной системы и пользовательских приложений с целью их профайлинга и отладки (еще иногда для security-аудита).
DTrace: пример профилирования
$ sudo dtrace \
-n 'profile-4999 /execname == "postgres"/ {@[ustack(1)] = count()}'
$ sudo dtrace \
-n 'profile-4999 /pid == 1234/ { @[ustack()] = count() }' \
-o out.dtrace
DTrace: строим флеймграф
$ git clone https://github.com/brendangregg/FlameGraph
$ perl ./FlameGraph/stackcollapse.pl out.dtrace > out_folded.dtrace
$ perl ./FlameGraph/flamegraph.pl ./out_folded.dtrace > fg.svg
Флеймграфы с bcc/eBPF
$ sudo /usr/share/bcc/tools/profile -df -p 32133 > out.profile
$ git clone https://github.com/brendangregg/FlameGraph
$ ./FlameGraph/flamegraph.pl --colors hot < out.profile > out.svg
Полезняшки из bcc-tools
Что осталось за кадром
Дополнительные материалы
Домашние задания
Вопросы и ответы.