Опустить некоторые подсистемы C++
Я заметил, что с помощью emscripten даже относительно небольшие файлы C++ можно быстро превратить в довольно большие файлы JavaScript. Пример:
#include <memory>
int main(int argc, char** argv) {
std::shared_ptr<int> sp(new int);
}
Скомпилируйте это с недавним emsdk, используя команду как
em++ -std=c++11 -s DISABLE_EXCEPTION_CATCHING=1 -s NO_FILESYSTEM=1 \
-s NO_BROWSER=1 -s NO_EXIT_RUNTIME=1 -O3 -o foo.js foo.cc
Полученный файл имеет размер более 400 КБ. С -g
брошенный я могу сделать
grep -n '^function _' foo.js | c++filt -_
и посмотрим, какие у нас там функции. Вот некоторые примеры:
std::__1::moneypunct<char, false>::do_thousands_sep() const
std::__1::locale::~locale()
std::__1::basic_string<wchar_t, …>::~basic_string()
std::__1::time_get<…>::__get_day(…) const
std::__1::codecvt<wchar_t, char, __mbstate_t>::codecvt(unsigned int)
std::__1::locale::__imp::install(std::__1::locale::facet*, long)
_printf_core
Я сам этого не называю, но, тем не менее, все функции включены. Вероятно, многие из них включены в некоторые таблицы виртуальных функций. Другие могут быть из-за статического инициализатора.
Если бы это был обычный код, связанный с одной общей библиотекой где-то на моем жестком диске; Я бы не стал возражать. Но пол-мегабайта в коде JavaScript, который нужно передать, только для одного общего указателя? Должен быть способ избежать этого.
1 ответ
Одним из реализованных здесь решений является просто разделение библиотеки C++ на несколько частей. Перемещая код, касающийся ввода-вывода и локали, в отдельную библиотеку, весь код, который может работать без этого, может избежать статического инициализатора подсистемы ввода-вывода, что приводит к зависимости от функций, описанных выше. К сожалению, это также повлияет strstream
по понятным причинам.
Обновление: поскольку вышестоящий коммит 301e4ad (впервые включен в выпуск 1.30.6), системные библиотеки больше не компилируются как единое целое. *.bc
файл, но вместо этого как *.a
статическая библиотека, которая содержит несколько отдельных объектов. Из них на самом деле связаны только необходимые, что значительно уменьшает размер кода для простых случаев.