Компоновщик пытается включить все неиспользуемые функции и экземпляры шаблонов даже с привязкой на уровне функций - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть библиотека, которая очень часто использует шаблоны, чтобы избежать многократного переписывания одного и того же кода. Но, как известно, это приводит к ужасным временам компиляции, а в Visual Studio - к тяжелому и медленному интеллекту, что делает кодирование на компьютере с 4 ГБ ОЗУ очень шумным.

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

Например, у меня есть:

// socket.h
template<class Protocol>
class socket
{

};

// socket.cpp
template class socket<tcp>;
template class socket<udp>;
template class socket<local::tcp>;
template class socket<local::udp>;

// sslstream.h
template<class NextLayer, class Engine>
class sslstream
{

};

// sslstream.cpp
template class sslstream<tcp::socket, openssl::engine>;
template class sslstream<tcp::socket, wolfssl::engine>;
template class sslstream<udp::socket, openssl::engine>;
template class sslstream<udp::socket, wolfssl::engine>;
// and so on


// websocket.h
template<class NextLayer>
class wsstream
{

};

// websocket.cpp
template class wsstream<tcp::socket>;
template class wsstream<sslstream<tcp::socket, openssl::engine>>;
// and so on for all possible layers

Проблемы начинаются, когда я пытаюсь использовать что-то вроде wsstream<tcp::socket> в любом источнике, который ссылается на библиотеку. Линкер пытается включить все нестатические c функции и все экземпляры шаблонов по пути и выдаст ошибки для неразрешенных функций из библиотек openssl и wolfssl, если я не передам их компоновщику. Это увеличивает размер программы и включает в себя тонны неиспользуемого кода из openssl и wolfssl, даже если я вообще не использую ssl-функциональность! И десятки экземпляров шаблона будут включены и никогда не будут ссылаться только потому, что они создаются в одном и том же модуле перевода!

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

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

Вот что я сделал:

  • Включено связывание на уровне функций в проект библиотеки / Gy

  • Включить генерацию временного кода связи / LTCG в проекте программы, а также / Gy

Полученный файл lib был настолько огромным : более 60 МБ! Раньше было около 8 МБ.

Я ожидал, что теперь компоновщик не сможет включать неиспользуемый код, но результат exe не уменьшился в размере, а также имел много кода и строк из openssl и wolfssl!

Это ожидаемый результат? Или я что-то не так делаю? и если это предусмотрено, существует ли какой-либо метод, позволяющий отделить реализацию от шаблонных интерфейсов и не принуждать к включению целых экземпляров?

1 Ответ

0 голосов
/ 08 апреля 2020

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

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

Теперь каждый экземпляр находится в своем собственном файле, и компоновщик выиграл не тяните неиспользуемые моменты.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...