Autoload less libraries
In previous allmodules&autoloading patch, we used callback from DeserializationListener to get Decl and loaded corresponding libraries. It worked, but the performance was bad because ROOT was loading excessive libraries. In this patch, we use TCling::LazyFunctionCreatorAutoloadForModule. This function gets callback when "mangled_name" was not found in loaded libraries thus we have to the load corresponding library and lookup again. I used unordered_map to store mangled identifier and library pair. I'm doing an optimization by hashing mangled name and storing library not by name but by uint8 and hold uint8-name information in another vector. Also tried std::map but unorderd_map was more performant. There are better hash table like: https://probablydance.com/2018/05/28/a-new-fast-hash-table-in-response-to-googles-new-fast-hash-table/ we can try to use them if this part gets crucial. With this patch: ``` Processing tutorials/hsimple.C... hsimple : Real Time = 0.04 seconds Cpu Time = 0.03 seconds (TFile *) 0x562b37a14fe0 Processing /home/yuka/CERN/ROOT/memory.C... cpu time = 0.362307 seconds sys time = 0.039741 seconds res memory = 278.215 Mbytes vir memory = 448.973 Mbytes ``` W/o this patch: ``` Processing tutorials/hsimple.C... hsimple : Real Time = 0.08 seconds Cpu Time = 0.07 seconds (TFile *) 0x5563018a1d30 Processing /home/yuka/CERN/ROOT/memory.C... cpu time = 1.524314 seconds sys time = 0.157075 seconds res memory = 546.867 Mbytes vir memory = 895.184 Mbytes ``` So it improves time by 4x times and memory by 2x.
This commit is contained in:
parent
eb9fbe9f2c
commit
35a8988d50
@ -132,13 +132,6 @@ namespace cling {
|
||||
///
|
||||
virtual void TransactionCommitted(const Transaction&) {}
|
||||
|
||||
///\brief This callback is invoked before a transaction is executed.
|
||||
/// This event happens after a transaction was committed and LLVM IR was produced.
|
||||
///
|
||||
///\param[in] - The transaction to be executed.
|
||||
///
|
||||
virtual void beforeExecuteTransaction(const Transaction&) {}
|
||||
|
||||
///\brief This callback is invoked whenever interpreter has reverted a
|
||||
/// transaction that has been fully committed.
|
||||
///
|
||||
|
@ -31,7 +31,6 @@ namespace clang {
|
||||
class Preprocessor;
|
||||
struct PrintingPolicy;
|
||||
class Sema;
|
||||
class Module;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
@ -116,11 +115,6 @@ namespace cling {
|
||||
typedef llvm::SmallVector<DelayCallInfo, 64> DeclQueue;
|
||||
typedef llvm::SmallVector<Transaction*, 2> NestedTransactions;
|
||||
|
||||
///\brief The list of cxxmodules, which is collected by DeserializationListener
|
||||
/// and will be used to load corresponding libraries.
|
||||
///
|
||||
std::vector<clang::Module*> m_CxxModules;
|
||||
|
||||
///\brief All seen declarations, except the deserialized ones.
|
||||
/// If we collect the declarations by walking the clang::DeclContext we
|
||||
/// will miss the injected onces (eg. template instantiations).
|
||||
@ -274,17 +268,6 @@ namespace cling {
|
||||
return const_reverse_nested_iterator(0);
|
||||
}
|
||||
|
||||
void addClangModule(clang::Module* M) {
|
||||
assert(M && "addClangModules: passed clang::Module pointer is null");
|
||||
|
||||
if (std::find(m_CxxModules.rbegin(), m_CxxModules.rend(), M) == m_CxxModules.rend())
|
||||
m_CxxModules.push_back(M);
|
||||
}
|
||||
|
||||
const std::vector<clang::Module*> &getClangModules() const {
|
||||
return m_CxxModules;
|
||||
}
|
||||
|
||||
/// Macro iteration
|
||||
typedef MacroDirectiveInfoQueue::iterator macros_iterator;
|
||||
typedef MacroDirectiveInfoQueue::const_iterator const_macros_iterator;
|
||||
|
@ -321,17 +321,4 @@ namespace cling {
|
||||
m_Consumer->HandleCXXStaticMemberVarInstantiation(D);
|
||||
}
|
||||
|
||||
void DeclCollector::DeclRead(clang::serialization::DeclID, const clang::Decl *D) {
|
||||
assertHasTransaction(m_CurTransaction);
|
||||
|
||||
assert(D && "Decl doesn't exist!");
|
||||
if (!D->hasOwningModule()) return;
|
||||
|
||||
clang::Module *M = D->getOwningModule();
|
||||
M = M->getTopLevelModule();
|
||||
|
||||
// Add interesting module to Transaction's m_cxxmodules; Corresponding library will be loaded.
|
||||
m_CurTransaction->addClangModule(M);
|
||||
}
|
||||
|
||||
} // namespace cling
|
||||
|
@ -11,7 +11,6 @@
|
||||
#define CLING_DECL_COLLECTOR_H
|
||||
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||
|
||||
#include "ASTTransformer.h"
|
||||
|
||||
@ -25,7 +24,6 @@ namespace clang {
|
||||
class DeclGroupRef;
|
||||
class Preprocessor;
|
||||
class Token;
|
||||
class Module;
|
||||
}
|
||||
|
||||
namespace cling {
|
||||
@ -42,7 +40,7 @@ namespace cling {
|
||||
/// cling::DeclCollector is responsible for appending all the declarations
|
||||
/// seen by clang.
|
||||
///
|
||||
class DeclCollector : public clang::ASTConsumer , public clang::ASTDeserializationListener {
|
||||
class DeclCollector : public clang::ASTConsumer {
|
||||
/// \brief PPCallbacks overrides/ Macro support
|
||||
class PPAdapter;
|
||||
|
||||
@ -118,11 +116,6 @@ namespace cling {
|
||||
|
||||
// dyn_cast/isa support
|
||||
static bool classof(const clang::ASTConsumer*) { return true; }
|
||||
static bool classof(const clang::ASTDeserializationListener*) { return true; }
|
||||
|
||||
///\brief ASTDeserializationListener function which gets callback when a decl is deserialized
|
||||
void DeclRead(clang::serialization::DeclID, const clang::Decl *D) final;
|
||||
|
||||
};
|
||||
} // namespace cling
|
||||
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/SemaDiagnostic.h"
|
||||
#include "clang/Serialization/ASTWriter.h"
|
||||
#include "clang/Serialization/ASTReader.h"
|
||||
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
@ -227,13 +226,6 @@ namespace cling {
|
||||
Preprocessor& PP = m_CI->getPreprocessor();
|
||||
DiagnosticsEngine& Diags = m_CI->getSema().getDiagnostics();
|
||||
|
||||
ASTReader* Reader = m_CI->getModuleManager().get();
|
||||
assert(isa<ASTDeserializationListener>(m_Consumer));
|
||||
ASTDeserializationListener* Listener = cast<ASTDeserializationListener>(m_Consumer);
|
||||
// FIXME: We should create a multiplexing deserialization listener if there is one already attached.
|
||||
if (Reader && Listener && !Reader->getDeserializationListener())
|
||||
Reader->setDeserializationListener(Listener);
|
||||
|
||||
// Pull in PCH.
|
||||
const std::string& PCHFileName
|
||||
= m_CI->getInvocation().getPreprocessorOpts().ImplicitPCHInclude;
|
||||
|
@ -1529,9 +1529,6 @@ namespace cling {
|
||||
assert(!isInSyntaxOnlyMode() && "Running on what?");
|
||||
assert(T.getState() == Transaction::kCommitted && "Must be committed");
|
||||
|
||||
if (InterpreterCallbacks* callbacks = getCallbacks())
|
||||
callbacks->beforeExecuteTransaction(T);
|
||||
|
||||
const std::shared_ptr<llvm::Module>& M = T.getModule();
|
||||
if (!M)
|
||||
return Interpreter::kExeNoModule;
|
||||
|
@ -1452,9 +1452,9 @@ namespace cling {
|
||||
|
||||
DigestArgsInput inputEval;
|
||||
llvm::SmallVector<Expr*, 4> GivenArgs;
|
||||
Interpreter::PushTransactionRAII pushedT(Interp);
|
||||
if (!inputEval(GivenArgs,funcArgs,diagOnOff,P,Interp)) return 0;
|
||||
|
||||
Interpreter::PushTransactionRAII pushedT(Interp);
|
||||
return findFunction(foundDC,
|
||||
funcName, GivenArgs, objectIsConst,
|
||||
Context, Interp, functionSelector,
|
||||
|
@ -77,12 +77,6 @@ namespace cling {
|
||||
}
|
||||
}
|
||||
|
||||
void beforeExecuteTransaction(const Transaction& T) override {
|
||||
for (auto&& cb : m_Callbacks) {
|
||||
cb->beforeExecuteTransaction(T);
|
||||
}
|
||||
}
|
||||
|
||||
void TransactionUnloaded(const Transaction& T) override {
|
||||
for (auto&& cb : m_Callbacks) {
|
||||
cb->TransactionUnloaded(T);
|
||||
|
Loading…
x
Reference in New Issue
Block a user