Files
scylladb/marshal_exception.hh
Nadav Har'El 6ebf32f4d7 types: deinline template throw_with_backtrace<marshal_exception, sstring>
When a template is instantiated in a header file which is included by many
source files, the compiler needs to compile it again and again.
ClangBuildAnalyzer helps find the worst cases of this happening, and one
of the worst happens to be

   seastar::throw_with_backtrace<marshal_exception, sstring>

This specific template function takes (according to ClangBuildAnalyzer)
362 milliseconds to instantiate, and this is done 312 (!) times, because
it reaches virtually every Scylla source file via either types.hh or
compound.hh which use this idiom.

Unfortunately, C++ as it exists today does not have a mechanism to
avoid compiling a specific template instantiation if this was already
done in some other source file. But we can do this manually using
the C++11 feature of "extern template":

1. For a specific template instance, in this case
   seastar::throw_with_backtrace<marhsal_exception, sstring>,
   all source files except one specify it as "extern template".
   This means that the code for it will NOT be built in this source
   file, and the compiler assumes the linker will eventually supply it.

2. At the same time, one source file instantiates this template
   instance once regularly, without "extern".

The numbers from ClangBuildAnalyzer suggest that this patch should
reduce total build time by 1% (in dev build mode), but this is hard to
measure in practice because the very long build time (210 CPU minutes on
my laptop) usually fluctuates by more than 1% in consecutive runs.
However, we've seen in the past that a good estimate of build time is
the total produced object size (du -bc build/dev/**/*.o). This patch
indeed reduces this total object size (in dev build mode) by exactly 1%.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Message-Id: <20220105171453.308821-1-nyh@scylladb.com>
2022-01-05 19:23:40 +02:00

44 lines
1.5 KiB
C++

/*
* Copyright (C) 2017-present ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdexcept>
#include <seastar/core/sstring.hh>
#include "seastarx.hh"
class marshal_exception : public std::exception {
sstring _why;
public:
marshal_exception() = delete;
marshal_exception(sstring why) : _why(sstring("marshaling error: ") + why) {}
virtual const char* what() const noexcept override { return _why.c_str(); }
};
// Speed up compilation of code using throw_with_backtrace<marshal_exception,
// sstring> by compiling it only once (in types.cc), and elsewhere say that
// it is extern and not compile it again.
namespace seastar {
template <class Exc, typename... Args> [[noreturn]] void throw_with_backtrace(Args&&... args);
extern template void throw_with_backtrace<marshal_exception, sstring>(sstring&&);
}