summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-06-02 00:43:49 -0700
committerJosh Stone <jistone@redhat.com>2009-06-02 00:43:49 -0700
commitc8ad068755e7424e767660f2c27cb3b1e2d5343d (patch)
tree8d927da0ab13dac41b24560b5e472d2fa9e13e8e
parent276465828851648edc5b56f762a0d100051c9e32 (diff)
downloadsystemtap-steved-c8ad068755e7424e767660f2c27cb3b1e2d5343d.tar.gz
systemtap-steved-c8ad068755e7424e767660f2c27cb3b1e2d5343d.tar.xz
systemtap-steved-c8ad068755e7424e767660f2c27cb3b1e2d5343d.zip
Cache the last result of dwarf_getscopes
This one function accounted for ~30% of my callgrind profile of "stap -l 'syscall.*'", even though it was only called ~1200 times. We call dwarf_getscopes for each $target variable, with the same parameters within a given probe. Since they're no nicely grouped, it's easy to just cache the most recent call, and the next few calls will be a hit. Overall this cuts the number of calls down to about 300, for an easy speed gain.
-rw-r--r--dwflpp.cxx24
-rw-r--r--dwflpp.h5
2 files changed, 27 insertions, 2 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index 52981d3f..6ca9780d 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -66,7 +66,8 @@ static string TOK_KERNEL("kernel");
dwflpp::dwflpp(systemtap_session & session, const string& user_module):
sess(session), module(NULL), module_bias(0), mod_info(NULL),
module_start(0), module_end(0), cu(NULL), dwfl(NULL),
- module_dwarf(NULL), function(NULL), blacklist_enabled(false)
+ module_dwarf(NULL), function(NULL), blacklist_enabled(false),
+ pc_cached_scopes(0), num_cached_scopes(0), cached_scopes(NULL)
{
if (user_module.empty())
setup_kernel();
@@ -77,6 +78,7 @@ dwflpp::dwflpp(systemtap_session & session, const string& user_module):
dwflpp::~dwflpp()
{
+ free(cached_scopes);
if (dwfl)
dwfl_end(dwfl);
}
@@ -165,6 +167,9 @@ dwflpp::focus_on_cu(Dwarf_Die * c)
// Reset existing pointers and names
function_name.clear();
function = NULL;
+
+ free(cached_scopes);
+ cached_scopes = NULL;
}
@@ -1341,7 +1346,7 @@ dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die,
assert (cu);
- nscopes = dwarf_getscopes (cu, pc, &scopes);
+ nscopes = dwarf_getscopes_cached (pc, &scopes);
int sidx;
// if pc and scope_die are disjoint then we need dwarf_getscopes_die
for (sidx = 0; sidx < nscopes; sidx++)
@@ -2383,4 +2388,19 @@ dwflpp::relocate_address(Dwarf_Addr addr,
}
+int
+dwflpp::dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes)
+{
+ if (!cached_scopes || pc != pc_cached_scopes)
+ {
+ free(cached_scopes);
+ cached_scopes = NULL;
+ pc_cached_scopes = pc;
+ num_cached_scopes = dwarf_getscopes(cu, pc, &cached_scopes);
+ }
+ *scopes = cached_scopes;
+ return num_cached_scopes;
+}
+
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/dwflpp.h b/dwflpp.h
index 554e02d4..314e7583 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -382,6 +382,11 @@ private:
bool blacklist_enabled;
void build_blacklist();
std::string get_blacklist_section(Dwarf_Addr addr);
+
+ Dwarf_Addr pc_cached_scopes;
+ int num_cached_scopes;
+ Dwarf_Die *cached_scopes;
+ int dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes);
};
#endif // DWFLPP_H