Cache the incremental iterators as you traverse the list, so that you don't have to keep recomputing them
If memory turns out to be a problem, which I don't think it will in practice because all these ValueObjects, we'd be keeping alive anyway, I can always resort to caching the farthest-most iterator only This gains us an order of magnitude in my benchmark, cutting the time to traverse a 1500-elements list from 22 seconds down to 2 llvm-svn: 254762
This commit is contained in:
parent
4c8a5e37e2
commit
26935d9a09
|
@ -31,9 +31,6 @@ namespace {
|
|||
|
||||
class ListEntry
|
||||
{
|
||||
private:
|
||||
static const std::initializer_list<size_t> __prev_idx;
|
||||
static const std::initializer_list<size_t> __next_idx;
|
||||
public:
|
||||
ListEntry() = default;
|
||||
ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
|
||||
|
@ -102,6 +99,64 @@ namespace {
|
|||
private:
|
||||
ValueObjectSP m_entry_sp;
|
||||
};
|
||||
|
||||
class ListIterator
|
||||
{
|
||||
public:
|
||||
ListIterator() = default;
|
||||
ListIterator (ListEntry entry) : m_entry(entry) {}
|
||||
ListIterator (ValueObjectSP entry) : m_entry(entry) {}
|
||||
ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
|
||||
ListIterator (ValueObject* entry) : m_entry(entry) {}
|
||||
|
||||
ValueObjectSP
|
||||
value ()
|
||||
{
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
|
||||
ValueObjectSP
|
||||
advance (size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return m_entry.GetEntry();
|
||||
if (count == 1)
|
||||
{
|
||||
next ();
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
while (count > 0)
|
||||
{
|
||||
next ();
|
||||
count--;
|
||||
if (m_entry.null())
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
|
||||
bool
|
||||
operator == (const ListIterator& rhs) const
|
||||
{
|
||||
return (rhs.m_entry == m_entry);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
next ()
|
||||
{
|
||||
m_entry = m_entry.next();
|
||||
}
|
||||
|
||||
void
|
||||
prev ()
|
||||
{
|
||||
m_entry = m_entry.prev();
|
||||
}
|
||||
|
||||
private:
|
||||
ListEntry m_entry;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -146,68 +201,11 @@ namespace lldb_private {
|
|||
CompilerType m_element_type;
|
||||
size_t m_count;
|
||||
std::map<size_t,lldb::ValueObjectSP> m_children;
|
||||
std::map<size_t, ListIterator> m_iterators;
|
||||
};
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
class ListIterator
|
||||
{
|
||||
public:
|
||||
ListIterator() = default;
|
||||
ListIterator (ListEntry entry) : m_entry(entry) {}
|
||||
ListIterator (ValueObjectSP entry) : m_entry(entry) {}
|
||||
ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
|
||||
ListIterator (ValueObject* entry) : m_entry(entry) {}
|
||||
|
||||
ValueObjectSP
|
||||
value ()
|
||||
{
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
|
||||
ValueObjectSP
|
||||
advance (size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return m_entry.GetEntry();
|
||||
if (count == 1)
|
||||
{
|
||||
next ();
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
while (count > 0)
|
||||
{
|
||||
next ();
|
||||
count--;
|
||||
if (m_entry.null())
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
return m_entry.GetEntry();
|
||||
}
|
||||
|
||||
bool
|
||||
operator == (const ListIterator& rhs) const
|
||||
{
|
||||
return (rhs.m_entry == m_entry);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
next ()
|
||||
{
|
||||
m_entry = m_entry.next();
|
||||
}
|
||||
|
||||
void
|
||||
prev ()
|
||||
{
|
||||
m_entry = m_entry.prev();
|
||||
}
|
||||
|
||||
private:
|
||||
ListEntry m_entry;
|
||||
};
|
||||
|
||||
lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_list_capping_size(0),
|
||||
|
@ -217,7 +215,8 @@ m_head(NULL),
|
|||
m_tail(NULL),
|
||||
m_element_type(),
|
||||
m_count(UINT32_MAX),
|
||||
m_children()
|
||||
m_children(),
|
||||
m_iterators()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
|
@ -319,11 +318,26 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
|
|||
|
||||
if (HasLoop(idx+1))
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
|
||||
size_t actual_advance = idx;
|
||||
|
||||
ListIterator current(m_head);
|
||||
ValueObjectSP current_sp(current.advance(idx));
|
||||
if (idx > 0)
|
||||
{
|
||||
auto cached_iterator = m_iterators.find(idx-1);
|
||||
if (cached_iterator != m_iterators.end())
|
||||
{
|
||||
current = cached_iterator->second;
|
||||
actual_advance = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ValueObjectSP current_sp(current.advance(actual_advance));
|
||||
if (!current_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
m_iterators[idx] = current;
|
||||
|
||||
current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
|
||||
if (!current_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
@ -343,6 +357,7 @@ bool
|
|||
lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
|
||||
{
|
||||
m_children.clear();
|
||||
m_iterators.clear();
|
||||
m_head = m_tail = NULL;
|
||||
m_node_address = 0;
|
||||
m_count = UINT32_MAX;
|
||||
|
|
Loading…
Reference in New Issue