[Lldb-commits] [PATCH] optimize address range coalescing
Greg Clayton
gclayton at apple.com
Mon Apr 18 15:34:07 PDT 2011
Nice!
On Apr 15, 2011, at 6:40 AM, Stephen Wilson wrote:
>
> DWARFDebugAranges::Sort() calls std::stable_sort() over a set of address ranges
> and then proceeds to collapse neighboring ranges together.
>
> One problem with the current implementation is that it does an incomplete job.
> When a pair of ranges are merged the next pair considered does not include the
> just-merged range. IOW, three consecutive ranges are never collapsed into one.
>
> Another problem is that for each range merged we are calling
> std::vector::erase() which "shifts" all remaining elements of the vector by one
> position on every merge. The end result (in the worst case) is a quadratic
> algorithm -- not good when the input vector is large.
>
> The following patch merges all consecutive ranges and removes the quadratic
> behavior. The implementation uses an auxiliary vector of indices in order to
> remember all ranges that can be dropped, then performs the coalescing of ranges
> in a single pass.
>
> Instrumenting DWARFDebugAranges::Sort() with a timer and loading LLDB in LLDB
> prior to this patch gives (on my prone-to-overheat 2GHz laptop):
>
> Current executable set to './lldb' (x86_64).
> (lldb) break set -n main
> Breakpoint created: 1: name = 'main', locations = 1
> (lldb) log timers enable
> (lldb) r
> Process 12840 launched: '/home/steve/development/build/llvm-git/Debug+Asserts/bin/lldb' (x86_64)
> (lldb) Process 12840 stopped
> * thread #1: tid = 0x3228, 0x0000000000411fed lldb`main + 32 at Driver.cpp:1275, stop reason = breakpoint 1.1
> 1272 int
> 1273 main (int argc, char const *argv[], const char *envp[])
> 1274 {
> -> 1275 SBDebugger::Initialize();
> 1276
> 1277 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
> 1278
>
> (lldb) log timers dump
> 17.027432000 sec for void DWARFDebugAranges::Sort()
> ...
>
> and after this patch:
>
> ...
> (lldb) log timers dump
> ...
> 0.154519000 sec for void DWARFDebugAranges::Sort()
> ...
>
>
>
> diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
> index 8e3461d..2d69926 100644
> --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
> +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
> @@ -15,6 +15,7 @@
> #include <algorithm>
>
> #include "lldb/Core/Stream.h"
> +#include "lldb/Core/Timer.h"
>
> #include "SymbolFileDWARF.h"
> #include "DWARFDebugInfo.h"
> @@ -290,36 +291,46 @@ DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t
>
> void
> DWARFDebugAranges::Sort()
> -{
> - // Sort our address range entries
> +{
> + std::vector<size_t> indices;
> + size_t end;
> + Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
> + __PRETTY_FUNCTION__, this);
> +
> + // Sort our address range entries.
> std::stable_sort (m_aranges.begin(), m_aranges.end(), RangeLessThan);
>
> - // Merge any entries that have the same offset and same start/end address
> - RangeColl::iterator pos = m_aranges.begin();
> - RangeColl::iterator end = m_aranges.end();
> - while (pos != end)
> + // Merge all neighbouring ranges into a single range and remember the
> + // indices of all ranges merged.
> + end = m_aranges.size();
> + for (size_t merge = 0, cursor = 1; cursor < end; ++cursor)
> {
> - RangeColl::iterator next_pos = pos + 1;
> - if (next_pos != end &&
> - pos->offset == next_pos->offset &&
> - pos->hi_pc == next_pos->lo_pc)
> + Range &r1 = m_aranges[merge];
> + Range &r2 = m_aranges[cursor];
> +
> + if (r1.hi_pc == r2.lo_pc && r1.offset == r2.offset)
> {
> - // We have found an entry whose end address it he same as the
> - // next entry's start address and the offsets are the same so
> - // we can merge these two entries.
> - pos->hi_pc = next_pos->hi_pc;
> - // Erase the next entry that wasn't needed
> - pos = m_aranges.erase (next_pos);
> - // Now recompute the end of the collection
> - end = m_aranges.end();
> + r1.hi_pc = r2.hi_pc;
> + indices.push_back(cursor);
> }
> else
> - {
> - // Two entries have either different offsets or there are gaps
> - // in the address range, move along, nothing to see here.
> - pos = next_pos;
> - }
> + merge = cursor;
> }
> +
> + if (indices.empty())
> + return;
> +
> + // Remove the merged ranges by shifting down all the keepers...
> + indices.push_back(m_aranges.size());
> + end = indices.size();
> + for (size_t target = indices[0], cursor = 1; cursor < end; ++cursor)
> + {
> + for (size_t i = indices[cursor - 1] + 1; i < indices[cursor]; ++i)
> + m_aranges[target++] = m_aranges[i];
> + }
> +
> + // ...and drop the extra elements.
> + m_aranges.resize(m_aranges.size() - end + 1);
> }
>
> //----------------------------------------------------------------------
>
>
More information about the lldb-commits
mailing list