Полезна ли сборка мусора в разделе ссылок во время оптимизации времени ссылок?

Хорошо известно, что параметры gcc/ld -ffunction-sections -fdata-sections -Wl,--gc-sections может уменьшить двоичные размеры (см., например, ответы на запросы Query on -ffunction-section & -fdata-section gcc). Также хорошо известно, что оптимизация во время соединения может уменьшить двоичные размеры и скорость исполнения (см., Например, https://wiki.debian.org/LTO).

Но как насчет комбинации сборки мусора раздела и оптимизации времени соединения? Разве оптимизация во время компоновки не должна лишать сборщика мусора?

Я скомпилировал Open CASCADE ( https://www.opencascade.com/) с mingw-w64/g++ 9.2.0 с различными параметрами компилятора / компоновщика и только что сравнил двоичные размеры. Open CASCADE - это набор из нескольких библиотек. Большинство dll самые маленькие, если скомпилированы только с -flto, С помощью -flto -ffunction-sections -fdata-sections -Wl,--gc-sections вместо этого, в большинстве случаев немного увеличится размер двоичного файла. Но есть некоторые библиотеки, которые на самом деле становятся немного меньше при добавлении параметров сборки мусора.

Почему это так? Что может быть удалено с помощью сборки мусора, которую нельзя удалить с помощью простой оптимизации во время соединения? Есть ли лучшая практика, какую опцию компиляции / компоновки использовать для минимальных двоичных размеров?

Замечание: я предположил, что только -flto изменит время выполнения (мы надеемся, что исполняемые файлы будут быстрее!), а сборщик мусора в секции времени соединения, скорее всего, оставит время выполнения таким, какое оно есть. Я еще не нашел время, чтобы измерить это.


Редактировать: чтобы сделать описанное поведение воспроизводимым с помощью реальных общих библиотек, я создал скрипт bash для сборки Open CASCADE с двумя различными наборами параметров. Комментарии в первых строках описывают, как адаптировать скрипт. Я использую его здесь, в консоли MSYS2 на Windows.

#!/bin/bash

# This script requires at least CMake 3.13, otherwise the options "-S" and "-B" do not work as expected.
# Further it needs a mingw-w64 installation in the path.

# Path to the folder that has been downloaded and extracted from https://www.opencascade.com/sites/default/files/private/occt/OCC_7.3.0_release/opencascade-7.3.0.tgz
OCCT_PATH="/c/Libraries/opencascade-7.3.0"

# Path to the folder that has been downloaded and extracted from https://www.opencascade.com/sites/default/files/private/occt/3rdparty/freetype-2.6.3-mingw-64.7z
FREETYPE_PATH="/c/Libraries/freetype-2.6.3-mingw-64"

TEST_DIR="/c/Libraries/Test"

# Here the preparations are done... the script will (hopefully) do the rest.

if [ ! -d "$TEST_DIR" ]; then
    mkdir "$TEST_DIR"
fi


# Build with link-time optimization

BUILD_DIR_LTO="BuildLto"
INSTALL_DIR_LTO="InstallLto"

CMAKE_C_FLAGS_LTO="-O2 -DNDEBUG -flto"
CMAKE_CXX_FLAGS_LTO="$CMAKE_C_FLAGS_LTO -std=gnu++17"
# According to https://stackru.com/a/31688314/2492801 neither -flto nor an optimization flag is required with new gcc versions
CMAKE_SHARED_LINKER_FLAGS_LTO=""

cmake -DCMAKE_BUILD_TYPE="Release" -S "$OCCT_PATH" -B "$TEST_DIR/$BUILD_DIR_LTO" -G "MSYS Makefiles" -DINSTALL_DIR="$TEST_DIR/$INSTALL_DIR_LTO" -DCMAKE_CXX_FLAGS_RELEASE="$CMAKE_CXX_FLAGS_LTO" -DCMAKE_C_FLAGS_RELEASE="$CMAKE_C_FLAGS_LTO" -DCMAKE_SHARED_LINKER_FLAGS_RELEASE="$CMAKE_SHARED_LINKER_FLAGS_LTO" -DBUILD_MODULE_Draw=False -D3RDPARTY_FREETYPE_DIR="$FREETYPE_PATH"

cd "$TEST_DIR/$BUILD_DIR_LTO"
mingw32-make -j 24 install


# Build with link-time optimization and link-time section garbage collection

BUILD_DIR_GC="BuildLtoGc"
INSTALL_DIR_GC="InstallLtoGc"

CMAKE_C_FLAGS_GC="-O2 -DNDEBUG -flto -ffunction-sections -fdata-sections"
CMAKE_CXX_FLAGS_GC="$CMAKE_C_FLAGS_GC -std=gnu++17"
# According to https://stackru.com/a/31688314/2492801 neither -flto nor an optimization flag is required with new gcc versions
CMAKE_SHARED_LINKER_FLAGS_GC="-Wl,--gc-sections"

cmake -DCMAKE_BUILD_TYPE="Release" -S "$OCCT_PATH" -B "$TEST_DIR/$BUILD_DIR_GC" -G "MSYS Makefiles" -DINSTALL_DIR="$TEST_DIR/$INSTALL_DIR_GC" -DCMAKE_CXX_FLAGS_RELEASE="$CMAKE_CXX_FLAGS_GC" -DCMAKE_C_FLAGS_RELEASE="$CMAKE_C_FLAGS_GC" -DCMAKE_SHARED_LINKER_FLAGS_RELEASE="$CMAKE_SHARED_LINKER_FLAGS_GC" -DBUILD_MODULE_Draw=False -D3RDPARTY_FREETYPE_DIR="$FREETYPE_PATH"

cd "$TEST_DIR/$BUILD_DIR_GC"
mingw32-make -j 24 install

Файл Test/BuildLto/win64/gcc/bin/libTKGeomAlgo.dll имеет размер 4378624 байта, но Test/BuildLtoGc/win64/gcc/bin/libTKGeomAlgo.dll имеет размер 4377600 байт. Таким образом, дополнительная сборка мусора во время компоновки уменьшает размер файла даже больше, чем просто оптимизация во время компоновки. Почему???

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

0 ответов

Другие вопросы по тегам