Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Commit ac94caa

Browse files
author
Greg Clayton
committedJun 12, 2013
Huge performance improvements when one breakpoint contains many locations.
325,000 breakpoints for running "breakpoint set --func-regex ." on lldb itself (after hitting a breakpoint at main so that LLDB.framework is loaded) used to take up to an hour to set, now we are down under a minute. With warm file caches, we are at 40 seconds, and that is with setting 325,000 breakpoint through the GDB remote API. Linux and the native debuggers might be faster. I haven't timed what how much is debug info parsing and how much is the protocol traffic to/from GDB remote. That there were many performance issues. Most of them were due to storing breakpoints in the wrong data structures, or using the wrong iterators to traverse the lists, traversing the lists in inefficient ways, and not optimizing certain function name lookups/symbol merges correctly. Debugging after that is also now very efficient. There were issues with replacing the breakpoint opcodes in memory that was read, and those routines were also fixed. git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@183820 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c8b6859 commit ac94caa

21 files changed

+554
-1060
lines changed
 

‎include/lldb/Breakpoint/BreakpointSiteList.h

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// Other libraries and framework includes
1717
// Project includes
1818
#include "lldb/Breakpoint/BreakpointSite.h"
19+
#include "lldb/Host/Mutex.h"
1920

2021
namespace lldb_private {
2122

@@ -130,31 +131,8 @@ friend class Process;
130131
bool
131132
BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id);
132133

133-
//------------------------------------------------------------------
134-
/// Returns a shared pointer to the breakpoint site with index \a i.
135-
///
136-
/// @param[in] i
137-
/// The breakpoint site index to seek for.
138-
///
139-
/// @result
140-
/// A shared pointer to the breakpoint site. May contain a NULL pointer if the
141-
/// breakpoint doesn't exist.
142-
//------------------------------------------------------------------
143-
lldb::BreakpointSiteSP
144-
GetByIndex (uint32_t i);
145-
146-
//------------------------------------------------------------------
147-
/// Returns a shared pointer to the breakpoint site with index \a i - const version.
148-
///
149-
/// @param[in] i
150-
/// The breakpoint site index to seek for.
151-
///
152-
/// @result
153-
/// A shared pointer to the breakpoint site. May contain a NULL pointer if the
154-
/// breakpoint doesn't exist.
155-
//------------------------------------------------------------------
156-
const lldb::BreakpointSiteSP
157-
GetByIndex (uint32_t i) const;
134+
void
135+
ForEach (std::function <void(BreakpointSite *)> const &callback);
158136

159137
//------------------------------------------------------------------
160138
/// Removes the breakpoint site given by \b breakID from this list.
@@ -179,9 +157,6 @@ friend class Process;
179157
//------------------------------------------------------------------
180158
bool
181159
RemoveByAddress (lldb::addr_t addr);
182-
183-
void
184-
SetEnabledForAll(const bool enable, const lldb::break_id_t except_id = LLDB_INVALID_BREAK_ID);
185160

186161
bool
187162
FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const;
@@ -211,8 +186,18 @@ friend class Process;
211186
/// The number of elements.
212187
//------------------------------------------------------------------
213188
size_t
214-
GetSize() const { return m_bp_site_list.size(); }
189+
GetSize() const
190+
{
191+
Mutex::Locker locker(m_mutex);
192+
return m_bp_site_list.size();
193+
}
215194

195+
bool
196+
IsEmpty() const
197+
{
198+
Mutex::Locker locker(m_mutex);
199+
return m_bp_site_list.empty();
200+
}
216201
protected:
217202
typedef std::map<lldb::addr_t, lldb::BreakpointSiteSP> collection;
218203

@@ -222,13 +207,7 @@ friend class Process;
222207
collection::const_iterator
223208
GetIDConstIterator(lldb::break_id_t breakID) const;
224209

225-
// This function exposes the m_bp_site_list. I use the in Process because there
226-
// are places there where you want to iterate over the list, and it is less efficient
227-
// to do it by index. FIXME: Find a better way to do this.
228-
229-
const collection *
230-
GetMap ();
231-
210+
mutable Mutex m_mutex;
232211
collection m_bp_site_list; // The breakpoint site list.
233212
};
234213

‎include/lldb/Symbol/SymbolContext.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ class SymbolContextList
442442
AppendIfUnique (const SymbolContext& sc,
443443
bool merge_symbol_into_function);
444444

445+
bool
446+
MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
447+
uint32_t start_idx = 0,
448+
uint32_t stop_idx = UINT32_MAX);
449+
445450
uint32_t
446451
AppendIfUnique (const SymbolContextList& sc_list,
447452
bool merge_symbol_into_function);
@@ -485,6 +490,30 @@ class SymbolContextList
485490
bool
486491
GetContextAtIndex(size_t idx, SymbolContext& sc) const;
487492

493+
//------------------------------------------------------------------
494+
/// Direct reference accessor for a symbol context at index \a idx.
495+
///
496+
/// The index \a idx must be a valid index, no error checking will
497+
/// be done to ensure that it is valid.
498+
///
499+
/// @param[in] idx
500+
/// The zero based index into the symbol context list.
501+
///
502+
/// @return
503+
/// A const reference to the symbol context to fill in.
504+
//------------------------------------------------------------------
505+
SymbolContext&
506+
operator [] (size_t idx)
507+
{
508+
return m_symbol_contexts[idx];
509+
}
510+
511+
const SymbolContext&
512+
operator [] (size_t idx) const
513+
{
514+
return m_symbol_contexts[idx];
515+
}
516+
488517
//------------------------------------------------------------------
489518
/// Get accessor for the last symbol context in the list.
490519
///

‎source/Breakpoint/BreakpointResolverName.cpp

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ BreakpointResolverName::SearchCallback
188188
)
189189
{
190190
SymbolContextList func_list;
191-
SymbolContextList sym_list;
191+
//SymbolContextList sym_list;
192192

193193
uint32_t i;
194194
bool new_location;
@@ -203,11 +203,10 @@ BreakpointResolverName::SearchCallback
203203
log->Warning ("Class/method function specification not supported yet.\n");
204204
return Searcher::eCallbackReturnStop;
205205
}
206-
207-
const bool include_symbols = false;
206+
bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
207+
const bool include_symbols = filter_by_cu == false;
208208
const bool include_inlines = true;
209209
const bool append = true;
210-
bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
211210

212211
switch (m_match_type)
213212
{
@@ -228,26 +227,14 @@ BreakpointResolverName::SearchCallback
228227

229228
if (start_func_idx < end_func_idx)
230229
lookup.Prune (func_list, start_func_idx);
231-
// If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
232-
// symbols, since all the ones from a set compilation unit will have been found above already.
233-
else if (!filter_by_cu)
234-
{
235-
const size_t start_symbol_idx = sym_list.GetSize();
236-
context.module_sp->FindFunctionSymbols (lookup.lookup_name, lookup.name_type_mask, sym_list);
237-
const size_t end_symbol_idx = sym_list.GetSize();
238-
if (start_symbol_idx < end_symbol_idx)
239-
lookup.Prune (func_list, start_symbol_idx);
240-
}
241230
}
242231
}
243232
break;
244233
case Breakpoint::Regexp:
245234
if (context.module_sp)
246235
{
247-
if (!filter_by_cu)
248-
context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
249-
context.module_sp->FindFunctions (m_regex,
250-
include_symbols,
236+
context.module_sp->FindFunctions (m_regex,
237+
!filter_by_cu, // include symbols only if we aren't filterning by CU
251238
include_inlines,
252239
append,
253240
func_list);
@@ -281,33 +268,6 @@ BreakpointResolverName::SearchCallback
281268
SymbolContext sc;
282269
if (func_list.GetSize())
283270
{
284-
for (i = 0; i < func_list.GetSize(); i++)
285-
{
286-
if (func_list.GetContextAtIndex(i, sc) == false)
287-
continue;
288-
289-
if (sc.function == NULL)
290-
continue;
291-
uint32_t j = 0;
292-
while (j < sym_list.GetSize())
293-
{
294-
SymbolContext symbol_sc;
295-
if (sym_list.GetContextAtIndex(j, symbol_sc))
296-
{
297-
if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress())
298-
{
299-
if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress())
300-
{
301-
sym_list.RemoveContextAtIndex(j);
302-
continue; // Don't increment j
303-
}
304-
}
305-
}
306-
307-
j++;
308-
}
309-
}
310-
311271
for (i = 0; i < func_list.GetSize(); i++)
312272
{
313273
if (func_list.GetContextAtIndex(i, sc))
@@ -320,14 +280,21 @@ BreakpointResolverName::SearchCallback
320280
else if (sc.function)
321281
{
322282
break_addr = sc.function->GetAddressRange().GetBaseAddress();
323-
if (m_skip_prologue)
283+
if (m_skip_prologue && break_addr.IsValid())
324284
{
325-
if (break_addr.IsValid())
326-
{
327-
const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
328-
if (prologue_byte_size)
329-
break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
330-
}
285+
const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
286+
if (prologue_byte_size)
287+
break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
288+
}
289+
}
290+
else if (sc.symbol)
291+
{
292+
break_addr = sc.symbol->GetAddress();
293+
if (m_skip_prologue && break_addr.IsValid())
294+
{
295+
const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
296+
if (prologue_byte_size)
297+
break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
331298
}
332299
}
333300

@@ -351,35 +318,6 @@ BreakpointResolverName::SearchCallback
351318
}
352319
}
353320

354-
for (i = 0; i < sym_list.GetSize(); i++)
355-
{
356-
if (sym_list.GetContextAtIndex(i, sc))
357-
{
358-
if (sc.symbol && sc.symbol->ValueIsAddress())
359-
{
360-
break_addr = sc.symbol->GetAddress();
361-
362-
if (m_skip_prologue)
363-
{
364-
const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
365-
if (prologue_byte_size)
366-
break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
367-
}
368-
369-
if (filter.AddressPasses(break_addr))
370-
{
371-
BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
372-
if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
373-
{
374-
StreamString s;
375-
bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
376-
if (log)
377-
log->Printf ("Added location: %s\n", s.GetData());
378-
}
379-
}
380-
}
381-
}
382-
}
383321
return Searcher::eCallbackReturnContinue;
384322
}
385323

0 commit comments

Comments
 (0)
This repository has been archived.