Skip to content

[libc++] Extreme preprocessed size of core headers (vector, string, etc.) #80196

Closed
@wjakob

Description

@wjakob

Dear libc++ team,

I'm really concerned about growth in the preprocessed file size of core STL header files. For example, preprocessing a 1-liner like the following with -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES

#include <vector>

expands to 2 077 167 bytes (~2 megabytes)! Without the transitive include define, it is even larger at 2 467 776 (~2.4 megabytes). The problem with this is the cost that it imposes on every compilation unit for using something as simple as a std::vector.

Of those two megabytes of preprocessed code, only a tiny portion is ultimately concerned with std::vector.

Here are some of the things that get pulled in, for unclear reasons:

In file included from test.cpp:1:
In file included from /usr/include/c++/v1/vector:321:
In file included from /usr/include/c++/v1/__format/formatter_bool.h:17:
In file included from /usr/include/c++/v1/__format/concepts.h:17:
In file included from /usr/include/c++/v1/__format/format_parse_context.h:16:
In file included from /usr/include/c++/v1/string_view:246:
In file included from /usr/include/c++/v1/compare:145:
In file included from /usr/include/c++/v1/__compare/compare_partial_order_fallback.h:13:
In file included from /usr/include/c++/v1/__compare/partial_order.h:14:
In file included from /usr/include/c++/v1/__compare/weak_order.h:14:
In file included from /usr/include/c++/v1/__compare/strong_order.h:20:
In file included from /usr/include/c++/v1/cmath....

So using vector pulls in string (why), which pulls in __compare/strong_order.h, which pulls in the entire C & C++ math library, which is huge.

Major parts of tuple, locale, atomic, mutex, ctime, typeinfo, memory are also included as well.

Much of this growth seems related to C++20 features that have started to affect C++17 builds. For example all of the code in partial_order, weak_order, strong_order, etc. is actually #ifdef-ed out when compiling in C++17 mode. But that is only true for the body part. All of the dependent header files are still included. Here is an example from __compare/strong_order.h -basically all of the body code is disabled by #if _LIBCPP_STD_VER >= 20, but the #include directives at the top aren't.

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___COMPARE_STRONG_ORDER
#define _LIBCPP___COMPARE_STRONG_ORDER

#include <__bit/bit_cast.h>
#include <__compare/compare_three_way.h>
#include <__compare/ordering.h>
#include <__config>
#include <__type_traits/conditional.h>
#include <__type_traits/decay.h>
#include <__utility/forward.h>
#include <__utility/priority_tag.h>
#include <cmath>
#include <cstdint>
#include <limits>

#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
#  pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20

This issue is a plea for some attention for this issue. Would it make sense to benchmark libc++ header growth for central header files needed by many projects and start to work more actively against regressions? For projects that want to avoid the C++20+ header file growth, it would be great to trim these to what is truly needed in C++11, 14, or 17 builds.

Here are a few more examples, again all compiled in C++17 mode:

Header Preprocessed size
vector 2'046'574 bytes
iostream 1'906'216 bytes
algorithm 1'163'944 bytes
string 1'056'382 bytes
list 1'021'302 bytes
forward_list 1'003'060 bytes
iterator 965'992 bytes
array 739'743 bytes
variant 769'429 bytes
tuple 495'462 bytes
utility 427'718 bytes

Metadata

Metadata

Assignees

Labels

libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions