Author: enrico Date: Fri Dec 4 14:12:46 2015 New Revision: 254762 URL: http://llvm.org/viewvc/llvm-project?rev=254762&view=rev Log: 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 Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxList.cpp Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxList.cpp?rev=254762&r1=254761&r2=254762&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxList.cpp (original) +++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxList.cpp Fri Dec 4 14:12:46 2015 @@ -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::LibcxxStdListS 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; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits