From: Douglas Gregor Date: Tue, 1 Feb 2011 23:59:42 +0000 (+0000) Subject: Unique code-completion strings. On Cocoa.h, this costs us about 4% in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e349d2c61256f11180b7112ab592b4ae700f3dcf;p=clang Unique code-completion strings. On Cocoa.h, this costs us about 4% in speed but saves us about 25% of the memory usage for strings. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124704 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 8cb8e75393..bd9a868101 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -15,7 +15,9 @@ #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "clang-c/Index.h" @@ -421,11 +423,47 @@ public: std::string getAsString() const; }; +/// \brief \c DenseMap information object for StringRefs. +struct DenseMapStringRefInfo { + static inline llvm::StringRef getEmptyKey() { + return llvm::StringRef(reinterpret_cast((intptr_t)-1), 0); + } + static inline llvm::StringRef getTombstoneKey() { + return llvm::StringRef(reinterpret_cast((intptr_t)-2), 0); + } + static unsigned getHashValue(llvm::StringRef Str) { + return llvm::HashString(Str); + } + static bool isEqual(llvm::StringRef LHS, llvm::StringRef RHS) { + if (LHS.size() == 0 && RHS.size() == 0) { + intptr_t LHSVal = reinterpret_cast(LHS.data()); + intptr_t RHSVal = reinterpret_cast(RHS.data()); + if (LHSVal == -1 || LHSVal == -2 || RHSVal == -1 || RHSVal == -2) + return LHSVal == RHSVal; + + return true; + } + + return LHS == RHS; + } +}; + /// \brief An allocator used specifically for the purpose of code completion. class CodeCompletionAllocator : public llvm::BumpPtrAllocator { + llvm::DenseSet UniqueStrings; + unsigned StringBytesAllocated; + unsigned StringBytesUniqued; + unsigned StringsAllocated; + unsigned StringsUniqued; + public: + CodeCompletionAllocator(); + ~CodeCompletionAllocator(); + /// \brief Copy the given string into this allocator. const char *CopyString(llvm::StringRef String); + + void PrintStats(); }; /// \brief A builder class used to construct new code-completion strings. diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index cb2dd234b4..572c8dcbd0 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -220,10 +220,41 @@ const char *CodeCompletionString::getTypedText() const { return 0; } +CodeCompletionAllocator::CodeCompletionAllocator() + : llvm::BumpPtrAllocator(), StringBytesAllocated(0), StringBytesUniqued(0), + StringsAllocated(0), StringsUniqued(0) +{ +} + +CodeCompletionAllocator::~CodeCompletionAllocator() { } + +void CodeCompletionAllocator::PrintStats() { + llvm::errs() << "---Code completion memory allocation---\n" + << "String bytes uniqued: " << StringBytesUniqued << "/" + << StringBytesAllocated << " (" + << ((float)StringBytesUniqued*100/StringBytesAllocated) + << ")\nStrings uniqued: " << StringsUniqued << "/" << StringsAllocated + << " (" << ((float)StringsUniqued*100/StringsAllocated) + << ")\n"; + + llvm::BumpPtrAllocator::PrintStats(); +} + const char *CodeCompletionAllocator::CopyString(llvm::StringRef String) { + llvm::DenseSet::iterator Uniqued + = UniqueStrings.find(String); + ++StringsAllocated; + StringBytesAllocated += String.size() + 1; + if (Uniqued != UniqueStrings.end()) { + StringBytesUniqued += String.size() + 1; + ++StringsUniqued; + return Uniqued->data(); + } + char *Mem = (char *)Allocate(String.size() + 1, 1); std::copy(String.begin(), String.end(), Mem); Mem[String.size()] = 0; + UniqueStrings.insert(llvm::StringRef(Mem, String.size())); return Mem; }