Re-commit "Make dwarf parsing multi-threaded"

Re-commit the change after fixing a lot of race condition in LLDB
exposed by this change

Loading the debug info from a large application is the slowest task
LLDB do. This CL makes most of the dwarf parsing code multi-threaded.

As a result the speed of "attach; backtrace; exit;" when the inferior
is an LLDB with full debug info increased by a factor of 2.

Differential revision: http://reviews.llvm.org/D13662

llvm-svn: 251106
This commit is contained in:
Tamas Berghammer 2015-10-23 10:34:49 +00:00
parent d779da91de
commit 2ff8870b6f
3 changed files with 78 additions and 22 deletions

View File

@ -83,3 +83,14 @@ NameToDIE::ForEach (std::function <bool(const char *name, const DIERef& die_ref)
break;
}
}
void
NameToDIE::Append (const NameToDIE& other)
{
const uint32_t size = other.m_map.GetSize();
for (uint32_t i = 0; i < size; ++i)
{
m_map.Append(other.m_map.GetCStringAtIndexUnchecked (i),
other.m_map.GetValueAtIndexUnchecked (i));
}
}

View File

@ -37,6 +37,9 @@ public:
void
Insert (const lldb_private::ConstString& name, const DIERef& die_ref);
void
Append (const NameToDIE& other);
void
Finalize();

View File

@ -50,6 +50,8 @@
#include "lldb/Target/Language.h"
#include "lldb/Utility/TaskPool.h"
#include "DWARFASTParser.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugAbbrev.h"
@ -2015,37 +2017,77 @@ SymbolFileDWARF::Index ()
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
{
uint32_t cu_idx = 0;
const uint32_t num_compile_units = GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
std::vector<NameToDIE> function_basename_index(num_compile_units);
std::vector<NameToDIE> function_fullname_index(num_compile_units);
std::vector<NameToDIE> function_method_index(num_compile_units);
std::vector<NameToDIE> function_selector_index(num_compile_units);
std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
std::vector<NameToDIE> global_index(num_compile_units);
std::vector<NameToDIE> type_index(num_compile_units);
std::vector<NameToDIE> namespace_index(num_compile_units);
auto parser_fn = [this,
debug_info,
&function_basename_index,
&function_fullname_index,
&function_method_index,
&function_selector_index,
&objc_class_selectors_index,
&global_index,
&type_index,
&namespace_index](uint32_t cu_idx)
{
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1;
bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1;
dwarf_cu->Index(function_basename_index[cu_idx],
function_fullname_index[cu_idx],
function_method_index[cu_idx],
function_selector_index[cu_idx],
objc_class_selectors_index[cu_idx],
global_index[cu_idx],
type_index[cu_idx],
namespace_index[cu_idx]);
dwarf_cu->Index (m_function_basename_index,
m_function_fullname_index,
m_function_method_index,
m_function_selector_index,
m_objc_class_selectors_index,
m_global_index,
m_type_index,
m_namespace_index);
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if (clear_dies)
dwarf_cu->ClearDIEs (true);
dwarf_cu->ClearDIEs(true);
return cu_idx;
};
TaskRunner<uint32_t> task_runner;
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
task_runner.AddTask(parser_fn, cu_idx);
while (true)
{
std::future<uint32_t> f = task_runner.WaitForNextCompletedTask();
if (!f.valid())
break;
uint32_t cu_idx = f.get();
m_function_basename_index.Append(function_basename_index[cu_idx]);
m_function_fullname_index.Append(function_fullname_index[cu_idx]);
m_function_method_index.Append(function_method_index[cu_idx]);
m_function_selector_index.Append(function_selector_index[cu_idx]);
m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]);
m_global_index.Append(global_index[cu_idx]);
m_type_index.Append(type_index[cu_idx]);
m_namespace_index.Append(namespace_index[cu_idx]);
}
m_function_basename_index.Finalize();
m_function_fullname_index.Finalize();
m_function_method_index.Finalize();
m_function_selector_index.Finalize();
m_objc_class_selectors_index.Finalize();
m_global_index.Finalize();
m_type_index.Finalize();
m_namespace_index.Finalize();
TaskPool::RunTasks(
[&]() { m_function_basename_index.Finalize(); },
[&]() { m_function_fullname_index.Finalize(); },
[&]() { m_function_method_index.Finalize(); },
[&]() { m_function_selector_index.Finalize(); },
[&]() { m_objc_class_selectors_index.Finalize(); },
[&]() { m_global_index.Finalize(); },
[&]() { m_type_index.Finalize(); },
[&]() { m_namespace_index.Finalize(); });
#if defined (ENABLE_DEBUG_PRINTF)
StreamFile s(stdout, false);