[Lldb-commits] [lldb] r250289 - Change ConstString to support massive multi-threaded access
Tamas Berghammer via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 14 03:38:23 PDT 2015
Author: tberghammer
Date: Wed Oct 14 05:38:22 2015
New Revision: 250289
URL: http://llvm.org/viewvc/llvm-project?rev=250289&view=rev
Log:
Change ConstString to support massive multi-threaded access
Previously ConstString had a single mutex guarding the global string
pool for each access what become a bottleneck when using it with a
large number of threads.
This CL distributes the strings to 256 individual string pools based on
a simple hash function to eliminate the bottleneck and speed up the
multi-thread access.
The goal of the change is to prepare to multi-threaded symbol parsing code
to speed up the symbol parsing speed.
Differential revision: http://reviews.llvm.org/D13652
Modified:
lldb/trunk/source/Core/ConstString.cpp
Modified: lldb/trunk/source/Core/ConstString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConstString.cpp?rev=250289&r1=250288&r2=250289&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConstString.cpp (original)
+++ lldb/trunk/source/Core/ConstString.cpp Wed Oct 14 05:38:22 2015
@@ -8,39 +8,21 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Host/Mutex.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/RWMutex.h"
-#include <mutex> // std::once
+#include <array>
+#include <mutex>
using namespace lldb_private;
-
class Pool
{
public:
typedef const char * StringPoolValueType;
typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
-
- //------------------------------------------------------------------
- // Default constructor
- //
- // Initialize the member variables and create the empty string.
- //------------------------------------------------------------------
- Pool () :
- m_mutex (Mutex::eMutexTypeRecursive),
- m_string_map ()
- {
- }
-
- //------------------------------------------------------------------
- // Destructor
- //------------------------------------------------------------------
- ~Pool ()
- {
- }
-
static StringPoolEntryType &
GetStringMapEntryFromKeyData (const char *keyData)
@@ -85,20 +67,15 @@ public:
{
if (cstr)
return GetConstCStringWithLength (cstr, strlen (cstr));
- return NULL;
+ return nullptr;
}
const char *
GetConstCStringWithLength (const char *cstr, size_t cstr_len)
{
if (cstr)
- {
- Mutex::Locker locker (m_mutex);
- llvm::StringRef string_ref (cstr, cstr_len);
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
- return entry.getKeyData();
- }
- return NULL;
+ return GetConstCStringWithStringRef(llvm::StringRef(cstr, cstr_len));
+ return nullptr;
}
const char *
@@ -106,11 +83,20 @@ public:
{
if (string_ref.data())
{
- Mutex::Locker locker (m_mutex);
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
+ uint8_t h = hash (string_ref);
+
+ {
+ llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
+ auto it = m_string_pools[h].m_string_map.find (string_ref);
+ if (it != m_string_pools[h].m_string_map.end())
+ return it->getKeyData();
+ }
+
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (std::make_pair (string_ref, nullptr)).first;
return entry.getKeyData();
}
- return NULL;
+ return nullptr;
}
const char *
@@ -118,9 +104,12 @@ public:
{
if (demangled_cstr)
{
- Mutex::Locker locker (m_mutex);
+ llvm::StringRef string_ref (demangled_cstr);
+ uint8_t h = hash (string_ref);
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+
// Make string pool entry with the mangled counterpart already set
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;
+ StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (std::make_pair (string_ref, mangled_ccstr)).first;
// Extract the const version of the demangled_cstr
const char *demangled_ccstr = entry.getKeyData();
@@ -130,7 +119,7 @@ public:
// Return the constant demangled C string
return demangled_ccstr;
}
- return NULL;
+ return nullptr;
}
const char *
@@ -141,7 +130,7 @@ public:
const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
return GetConstCStringWithLength (cstr, trimmed_len);
}
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -152,28 +141,31 @@ public:
size_t
MemorySize() const
{
- Mutex::Locker locker (m_mutex);
size_t mem_size = sizeof(Pool);
- const_iterator end = m_string_map.end();
- for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
+ for (const auto& pool : m_string_pools)
{
- mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
+ llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex);
+ for (const auto& entry : pool.m_string_map)
+ mem_size += sizeof(StringPoolEntryType) + entry.getKey().size();
}
return mem_size;
}
protected:
- //------------------------------------------------------------------
- // Typedefs
- //------------------------------------------------------------------
- typedef StringPool::iterator iterator;
- typedef StringPool::const_iterator const_iterator;
+ uint8_t
+ hash(const llvm::StringRef &s)
+ {
+ uint32_t h = llvm::HashString(s);
+ return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
+ }
- //------------------------------------------------------------------
- // Member variables
- //------------------------------------------------------------------
- mutable Mutex m_mutex;
- StringPool m_string_map;
+ struct PoolEntry
+ {
+ mutable llvm::sys::SmartRWMutex<false> m_mutex;
+ StringPool m_string_map;
+ };
+
+ std::array<PoolEntry, 256> m_string_pools;
};
//----------------------------------------------------------------------
@@ -191,7 +183,7 @@ static Pool &
StringPool()
{
static std::once_flag g_pool_initialization_flag;
- static Pool *g_string_pool = NULL;
+ static Pool *g_string_pool = nullptr;
std::call_once(g_pool_initialization_flag, [] () {
g_string_pool = new Pool();
@@ -228,8 +220,8 @@ ConstString::operator < (const ConstStri
if (lhs_string_ref.data() && rhs_string_ref.data())
return lhs_string_ref < rhs_string_ref;
- // Else one of them was NULL, so if LHS is NULL then it is less than
- return lhs_string_ref.data() == NULL;
+ // Else one of them was nullptr, so if LHS is nullptr then it is less than
+ return lhs_string_ref.data() == nullptr;
}
Stream&
More information about the lldb-commits
mailing list