aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-08-22 21:02:52 -0700
committerRebecca Turner <rbt@sent.as>2024-08-28 09:52:05 -0700
commit4d8984420788d6253d2fd9bfa3ada92be8bfd73b (patch)
treed5db726ff1b87672c01f04e27064d5188d27d45a /src/libutil
parent422550fd68a5877534b1ca577fc3c7d89b6706dd (diff)
build: remove about 30 cpu-sec of compile time by explicit instantiation
Apparently the fmt contraption has some extremely popular overloads, and the boost stuff in there gets built approximately infinite times in every compilation unit. Change-Id: Ideba2db7d6bf8559e4d91974bab636f5ed106198
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/fmt.cc14
-rw-r--r--src/libutil/fmt.hh13
-rw-r--r--src/libutil/meson.build1
-rw-r--r--src/libutil/serialise.cc25
-rw-r--r--src/libutil/serialise.hh14
5 files changed, 52 insertions, 15 deletions
diff --git a/src/libutil/fmt.cc b/src/libutil/fmt.cc
new file mode 100644
index 000000000..400fb7ea0
--- /dev/null
+++ b/src/libutil/fmt.cc
@@ -0,0 +1,14 @@
+#include "fmt.hh" // IWYU pragma: keep
+
+template class boost::basic_format<char>;
+
+namespace nix {
+
+// Explicit instantiation saves about 30 cpu-seconds of compile time
+template HintFmt::HintFmt(const std::string &, const Uncolored<std::string> &s);
+template HintFmt::HintFmt(const std::string &, const std::string &s);
+template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &);
+
+HintFmt::HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
+
+}
diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh
index d015f7e5f..7589e51e2 100644
--- a/src/libutil/fmt.hh
+++ b/src/libutil/fmt.hh
@@ -3,7 +3,6 @@
#include <iostream>
#include <string>
-#include <optional>
#include <boost/format.hpp>
// Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace.
#if __APPLE__ || __FreeBSD__
@@ -12,6 +11,9 @@
#include <boost/stacktrace.hpp>
#include "ansicolor.hh"
+// Explicit instantiation in fmt.cc
+extern template class boost::basic_format<char>;
+
namespace nix {
/**
@@ -157,7 +159,9 @@ public:
* Format the given string literally, without interpolating format
* placeholders.
*/
- HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
+ // Moved out of line because it was instantiating the template below in
+ // every file in the project.
+ HintFmt(const std::string & literal);
/**
* Interpolate the given arguments into the format string.
@@ -193,6 +197,11 @@ public:
}
};
+// Explicit instantiations in fmt.cc
+extern template HintFmt::HintFmt(const std::string &, const Uncolored<std::string> &s);
+extern template HintFmt::HintFmt(const std::string &, const std::string &s);
+extern template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &);
+
std::ostream & operator<<(std::ostream & os, const HintFmt & hf);
}
diff --git a/src/libutil/meson.build b/src/libutil/meson.build
index 7c0e45e4b..e7f986363 100644
--- a/src/libutil/meson.build
+++ b/src/libutil/meson.build
@@ -17,6 +17,7 @@ libutil_sources = files(
'experimental-features.cc',
'file-descriptor.cc',
'file-system.cc',
+ 'fmt.cc',
'git.cc',
'hash.cc',
'hilite.cc',
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index a6dd7e200..4eda1b7e7 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -9,6 +9,31 @@
namespace nix {
+template<typename T>
+T readNum(Source & source)
+{
+ unsigned char buf[8];
+ source(charptr_cast<char *>(buf), sizeof(buf));
+
+ auto n = readLittleEndian<uint64_t>(buf);
+
+ if (n > (uint64_t) std::numeric_limits<T>::max())
+ throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name());
+
+ return (T) n;
+}
+
+template bool readNum<bool>(Source & source);
+
+template unsigned char readNum<unsigned char>(Source & source);
+
+template unsigned int readNum<unsigned int>(Source & source);
+
+template unsigned long readNum<unsigned long>(Source & source);
+template long readNum<long>(Source & source);
+
+template unsigned long long readNum<unsigned long long>(Source & source);
+template long long readNum<long long>(Source & source);
void BufferedSink::operator () (std::string_view data)
{
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh
index d6a22b3e9..9ad8018d0 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -450,19 +450,7 @@ inline Sink & operator<<(Sink & sink, const Error & ex)
MakeError(SerialisationError, Error);
template<typename T>
-T readNum(Source & source)
-{
- unsigned char buf[8];
- source(charptr_cast<char *>(buf), sizeof(buf));
-
- auto n = readLittleEndian<uint64_t>(buf);
-
- if (n > (uint64_t) std::numeric_limits<T>::max())
- throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name());
-
- return (T) n;
-}
-
+T readNum(Source & source);
inline unsigned int readInt(Source & source)
{