Skip to contentSkip to conversation

perf tools: fix handling of zero-length symbols.

PATCH In review Chris Phlipot 3 participants 6 messages May 7, 2016 – May 10, 2016 perf events

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 perf tools: fix handling of zero-length symbols.

This change introduces a fix to symbols__find, so that it is able to find symbols of length zero (where start==end)

The current code has the following problem:
-The current implementation of symbols__find is unable to find any symbols
of length zero.
-The db-export framework explicitly creates zero length symbols at
locations where no symbol currently exists.

The combination of the two above behaviors results in behavior similar to the example below.

1. addr_location is created for a sample, but symbol is unable to be resolved.
2. db export creates an "unknown" symbol of length zero at that address and inserts it into the dso.
3. A new sample comes in at the same address, but symbol__find is unable to find the zero length symbol, so it is still unresolved.
4. db export sees the symbol is unresolved, and allocated a duplicate symbol, even though it already did this in step 2.

This behavior continues every time an address without symbol information is seen, which causes a very large number of these symbols to be allocated.

The effect of this fix can be observed by looking at the contents of an exported database before/after the fix
(generated with scripts/python/export-to-postgresql.py)

Ex.
BEFORE THE CHANGE:
example_db=# select count(*) from symbols;
count
--------
900213
(1 row)

  example_db=# select count(*) from symbols where symbols.name='unknown';
   count
  --------
   897355
  (1 row)

  example_db=# select count(*) from symbols where symbols.name!='unknown';
   count
  -------
    2858
  (1 row)

AFTER THE CHANGE:

  example_db=# select count(*) from symbols;
   count
  -------
   25217
  (1 row)

  example_db=# select count(*) from symbols where name='unknown';
   count
  -------
   22359
  (1 row)

  example_db=# select count(*) from symbols where name!='unknown';
   count
  -------
    2858
  (1 row)
---
 tools/perf/util/symbol.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/symbol.c +3 -1
index 415c4f6..e42bf9a 100644
@@ -299,7 +299,9 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 	while (n) {
 		struct symbol *s = rb_entry(n, struct symbol, rb_node);
 
-		if (ip < s->start)
+		if (ip == s->start && s->start == s->end)
+			return s;
+		else if (ip < s->start)
 			n = n->rb_left;
 		else if (ip >= s->end)
 			n = n->rb_right;
Signature · 1 line
2.7.4
#1 lore raw

PATCH 2/2 perf script: fix incorrect python db-export error message

fix the error message printed when attempting and failing to create the call path root incorrectly references the call return process.

this change fixes the message to properly reference the failure to create the call path root.

---
 tools/perf/util/scripting-engines/trace-event-python.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/scripting-engines/trace-event-python.c +1 -1
index 091bce6..1546b74 100644
@@ -1062,7 +1062,7 @@ static void set_table_handlers(struct tables *tables)
 			tables->dbe.cpr = call_path_root__new();
 
 		if (!tables->dbe.cpr)
-			Py_FatalError("failed to create calls processor");
+			Py_FatalError("failed to create call path root");
 	}
 
 	tables->db_export_mode = true;
Signature · 1 line
2.7.4
#2 lore raw

[tip:perf/core] perf script: Fix incorrect python db-export error message

perf script: Fix incorrect python db-export error message
Commit-ID:  aff633406ca2772554bad7b37f2dfbc409b6ea74
Gitweb:     http://git.kernel.org/tip/aff633406ca2772554bad7b37f2dfbc409b6ea74
Author:     Chris Phlipot <[email protected]>
AuthorDate: Sat, 7 May 2016 02:17:00 -0700
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 9 May 2016 14:08:39 -0300

perf script: Fix incorrect python db-export error message

Fix the error message printed when attempting and failing to create the call path root incorrectly references the call return process.

This change fixes the message to properly reference the failure to create the call path root.

---
 tools/perf/util/scripting-engines/trace-event-python.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/scripting-engines/trace-event-python.c +1 -1
index 091bce6..1546b74 100644
@@ -1062,7 +1062,7 @@ static void set_table_handlers(struct tables *tables)
 			tables->dbe.cpr = call_path_root__new();
 
 		if (!tables->dbe.cpr)
-			Py_FatalError("failed to create calls processor");
+			Py_FatalError("failed to create call path root");
 	}
 
 	tables->db_export_mode = true;
#3 lore raw
In reply to Chris Phlipot

Em Sat, May 07, 2016 at 02:16:59AM -0700, Chris Phlipot escreveu:

Quoted 11 lines

This change introduces a fix to symbols__find, so that it is able to find symbols of length zero (where start==end)

The current code has the following problem:

(quoted diff) +0 -2
-The current implementation of symbols__find is unable to find any symbols
 of length zero.
-The db-export framework explicitly creates zero length symbols at
 locations where no symbol currently exists.

The combination of the two above behaviors results in behavior similar to the example below.

Ok, but you made the unlikely case be the first test, how about this one liner instead?

tools/perf/util/symbol.c +1 -1
index 415c4f6d98fd..7a0917569fb3 100644
@@ -301,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 
 		if (ip < s->start)
 			n = n->rb_left;
-		else if (ip >= s->end)
+		else if (ip > s->end || (ip == s->end && ip != s->start)
 			n = n->rb_right;
 		else
 			return s;
Quoted 14 lines

+++ b/tools/perf/util/symbol.c

(quoted diff) +3 -1
@@ -299,7 +299,9 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 	while (n) {
 		struct symbol *s = rb_entry(n, struct symbol, rb_node);
 
-		if (ip < s->start)
+		if (ip == s->start && s->start == s->end)
+			return s;
+		else if (ip < s->start)
 			n = n->rb_left;
 		else if (ip >= s->end)
 			n = n->rb_right;
Signature · 1 line
2.7.4
#4 lore raw
Quoted 26 lines · Arnaldo Carvalho de Melo

Em Sat, May 07, 2016 at 02:16:59AM -0700, Chris Phlipot escreveu:

Quoted 11 lines

This change introduces a fix to symbols__find, so that it is able to find symbols of length zero (where start==end)

The current code has the following problem:
-The current implementation of symbols__find is unable to find any symbols of length zero.
-The db-export framework explicitly creates zero length symbols at locations where no symbol currently exists.

The combination of the two above behaviors results in behavior similar to the example below.

Ok, but you made the unlikely case be the first test, how about this one liner instead?

tools/perf/util/symbol.c +0 -0
index 415c4f6d98fd..7a0917569fb3 100644

tools/perf/util/symbol.c static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) · line 307

Quoted 8 lines
tools/perf/util/symbol.c +1 -1
@@ -301,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 
       if (ip < s->start)
           n = n->rb_left;
-        else if (ip >= s->end)
+        else if (ip > s->end || (ip == s->end && ip != s->start)
           n = n->rb_right;
       else
           return s;

I agree. This looks like a better fix.

Quoted 14 lines
Quoted 14 lines

+++ b/tools/perf/util/symbol.c

(quoted diff) +3 -1
@@ -299,7 +299,9 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
   while (n) {
       struct symbol *s = rb_entry(n, struct symbol, rb_node);
 
-        if (ip < s->start)
+        if (ip == s->start && s->start == s->end)
+            return s;
+        else if (ip < s->start)
           n = n->rb_left;
       else if (ip >= s->end)
           n = n->rb_right;
Signature · 1 line
2.7.4
#5 lore raw

[tip:perf/core] perf symbols: Fix handling of zero-length symbols.

In reply to Chris Phlipot
perf symbols: Fix handling of zero-length symbols.
Commit-ID:  9c7b37cd63d0d910c531233209286f169993cbd9
Gitweb:     http://git.kernel.org/tip/9c7b37cd63d0d910c531233209286f169993cbd9
Author:     Chris Phlipot <[email protected]>
AuthorDate: Sat, 7 May 2016 02:16:59 -0700
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 9 May 2016 18:40:03 -0300

perf symbols: Fix handling of zero-length symbols.

This change introduces a fix to symbols__find, so that it is able to find symbols of length zero (where start == end).

The current code has the following problem:

- The current implementation of symbols__find is unable to find any symbols of length zero.

- The db-export framework explicitly creates zero length symbols at locations where no symbol currently exists.

The combination of the two above behaviors results in behavior similar to the example below.

1. addr_location is created for a sample, but symbol is unable to be resolved.

2. db export creates an "unknown" symbol of length zero at that address and inserts it into the dso.

3. A new sample comes in at the same address, but symbol__find is unable to find the zero length symbol, so it is still unresolved.

4. db export sees the symbol is unresolved, and allocated a duplicate symbol, even though it already did this in step 2.

This behavior continues every time an address without symbol information is seen, which causes a very large number of these symbols to be allocated.

The effect of this fix can be observed by looking at the contents of an exported database before/after the fix (generated with scripts/python/export-to-postgresql.py)

Ex.
BEFORE THE CHANGE:

  example_db=# select count(*) from symbols;
   count
  --------
   900213
  (1 row)

  example_db=# select count(*) from symbols where symbols.name='unknown';
   count
  --------
   897355
  (1 row)

  example_db=# select count(*) from symbols where symbols.name!='unknown';
   count
  -------
    2858
  (1 row)

AFTER THE CHANGE:

  example_db=# select count(*) from symbols;
   count
  -------
   25217
  (1 row)

  example_db=# select count(*) from symbols where name='unknown';
   count
  -------
   22359
  (1 row)

  example_db=# select count(*) from symbols where name!='unknown';
   count
  -------
    2858
  (1 row)
Cc Adrian Hunter <[email protected]>
Cc Peter Zijlstra <[email protected]>
[ Moved the test to later in the rb_tree tests, as this not the likely case ]
---
 tools/perf/util/symbol.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/symbol.c +1 -1
index 415c4f6..2946295 100644
@@ -301,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 
 		if (ip < s->start)
 			n = n->rb_left;
-		else if (ip >= s->end)
+		else if (ip > s->end || (ip == s->end && ip != s->start))
 			n = n->rb_right;
 		else
 			return s;