[Tarantool-patches] [PATCH luajit v1 2/4] memprof: demangle symbols on the spot

Mikhail Shishatskiy m.shishatskiy at tarantool.org
Sat Aug 21 15:50:00 MSK 2021


There may be situations, when new prototype has the same address than
the previously dumped one. In this case, the new symtab entry will
shadow the preceeding, and if we demangle symbols when all the events
are parsed, we can get irrelevant information:

| Dump symtab on the start:
|   addr  name
| * 0x001 proto_1
| * 0x002 proto_2
| * 0x003 proto_3
|
| Memprof running:
| ...
| * alloc: 0x001 proto_1
| // 0x001 proto_1 collected by the GC
| // new proto loaded on the 0x001 address
| * alloc: 0x001 proto_NEW
|   + symtab enriching -> [0x001] = proto_NEW

If we demangle symbols in the end, we will get 2 allocations
by proto_NEW because of the collision. But since symtab enriching
is implemented, we have enough information to avoid collision
while parsing events, demangling now happens on the spot, while
symtab entries are not shadowed by new ones.

Follows up tarantool/tarantool#5815
---

Issue: https://github.com/tarantool/tarantool/issues/5815
Branch: https://github.com/tarantool/luajit/tree/shishqa/gh-5815-enrich-symtab-when-prototype-is-allocated
Tarantool branch: https://github.com/tarantool/tarantool/tree/shishqa/gh-5815-enrich-symtab-when-prototype-is-allocated

 tools/memprof.lua          |  4 ++--
 tools/memprof/humanize.lua | 16 ++++++++--------
 tools/memprof/parse.lua    | 26 +++++++++++++-------------
 tools/memprof/process.lua  | 12 +++++-------
 4 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/tools/memprof.lua b/tools/memprof.lua
index 18b44fdd..496a0d78 100644
--- a/tools/memprof.lua
+++ b/tools/memprof.lua
@@ -102,9 +102,9 @@ local function dump(inputfile)
   local symbols = symtab.parse(reader)
   local events = memprof.parse(reader, symbols)
   if not leak_only then
-    view.profile_info(events, symbols)
+    view.profile_info(events)
   end
-  local dheap = process.form_heap_delta(events, symbols)
+  local dheap = process.form_heap_delta(events)
   view.leak_info(dheap)
   os.exit(0)
 end
diff --git a/tools/memprof/humanize.lua b/tools/memprof/humanize.lua
index 800a465e..0360362d 100644
--- a/tools/memprof/humanize.lua
+++ b/tools/memprof/humanize.lua
@@ -7,7 +7,7 @@ local symtab = require "utils.symtab"
 
 local M = {}
 
-function M.render(events, symbols)
+function M.render(events)
   local ids = {}
 
   for id, _ in pairs(events) do
@@ -21,15 +21,15 @@ function M.render(events, symbols)
   for i = 1, #ids do
     local event = events[ids[i]]
     print(string.format("%s: %d events\t+%d bytes\t-%d bytes",
-      M.describe_location(symbols, event.loc),
+      ids[i],
       event.num,
       event.alloc,
       event.free
     ))
 
     local prim_loc = {}
-    for _, heap_chunk in pairs(event.primary) do
-      table.insert(prim_loc, M.describe_location(symbols, heap_chunk.loc))
+    for id, _ in pairs(event.primary) do
+      table.insert(prim_loc, id)
     end
     if #prim_loc ~= 0 then
       table.sort(prim_loc)
@@ -42,17 +42,17 @@ function M.render(events, symbols)
   end
 end
 
-function M.profile_info(events, symbols)
+function M.profile_info(events)
   print("ALLOCATIONS")
-  M.render(events.alloc, symbols)
+  M.render(events.alloc)
   print("")
 
   print("REALLOCATIONS")
-  M.render(events.realloc, symbols)
+  M.render(events.realloc)
   print("")
 
   print("DEALLOCATIONS")
-  M.render(events.free, symbols)
+  M.render(events.free)
   print("")
 end
 
diff --git a/tools/memprof/parse.lua b/tools/memprof/parse.lua
index 888c6636..a540360b 100644
--- a/tools/memprof/parse.lua
+++ b/tools/memprof/parse.lua
@@ -9,6 +9,7 @@ local band = bit.band
 local lshift = bit.lshift
 
 local symtab = require "utils.symtab"
+local humanize = require "memprof.humanize"
 
 local string_format = string.format
 
@@ -66,12 +67,13 @@ local function link_to_previous(heap_chunk, e, nsize)
   end
 end
 
-local function id_location(addr, line, traceno)
-  return string_format("f%#xl%dt%d", addr, line, traceno), {
+local function id_location(addr, line, traceno, symbols)
+  local loc =  {
     addr = addr,
     line = line,
     traceno = traceno,
   }
+  return humanize.describe_location(symbols, loc), loc
 end
 
 local function parse_location_symbols(reader, asource, symbols)
@@ -79,21 +81,22 @@ local function parse_location_symbols(reader, asource, symbols)
     return id_location(
       symtab.parse_sym_lfunc(reader, symbols),
       reader:read_uleb128(),
-      0
+      0,
+      symbols
     )
   end
   error("Unknown asource "..asource)
 end
 
-local function parse_location_common(reader, asource)
+local function parse_location_common(reader, asource, symbols)
   if asource == ASOURCE_INT then
-    return id_location(0, 0, 0)
+    return id_location(0, 0, 0, symbols)
   elseif asource == ASOURCE_CFUNC then
-    return id_location(reader:read_uleb128(), 0, 0)
+    return id_location(reader:read_uleb128(), 0, 0, symbols)
   elseif asource == ASOURCE_LFUNC then
-    return id_location(reader:read_uleb128(), reader:read_uleb128(), 0)
+    return id_location(reader:read_uleb128(), reader:read_uleb128(), 0, symbols)
   elseif asource == ASOURCE_TRACE then
-    return id_location(reader:read_uleb128(), 0, reader:read_uleb128())
+    return id_location(reader:read_uleb128(), 0, reader:read_uleb128(), symbols)
   end
   error("Unknown asource "..asource)
 end
@@ -101,13 +104,10 @@ end
 local function parse_location(reader, asource, symbols)
   local has_symbols  = band(asource, LJM_SYMTAB)
   local asource_type = band(asource, ASOURCE_TYPE_MASK)
-  local id, loc
   if has_symbols == LJM_SYMTAB then
-    id, loc = parse_location_symbols(reader, asource_type, symbols)
-  else
-    id, loc = parse_location_common(reader, asource_type)
+    return parse_location_symbols(reader, asource_type, symbols)
   end
-  return id, loc
+  return parse_location_common(reader, asource_type, symbols)
 end
 
 local function parse_alloc(reader, asource, events, heap, symbols)
diff --git a/tools/memprof/process.lua b/tools/memprof/process.lua
index f277ed84..0a39d333 100644
--- a/tools/memprof/process.lua
+++ b/tools/memprof/process.lua
@@ -2,9 +2,7 @@
 
 local M = {}
 
-local humanize = require "memprof.humanize"
-
-function M.form_heap_delta(events, symbols)
+function M.form_heap_delta(events)
   -- Auto resurrects source event lines for counting/reporting.
   local dheap = setmetatable({}, {__index = function(t, line)
     rawset(t, line, {
@@ -15,9 +13,9 @@ function M.form_heap_delta(events, symbols)
     return t[line]
   end})
 
-  for _, event in pairs(events.alloc) do
+  for id, event in pairs(events.alloc) do
     if event.loc then
-      local ev_line = humanize.describe_location(symbols, event.loc)
+      local ev_line = id
 
       if (event.alloc > 0) then
         dheap[ev_line].dbytes = dheap[ev_line].dbytes + event.alloc
@@ -36,8 +34,8 @@ function M.form_heap_delta(events, symbols)
       -- Realloc and free events always have key named "primary"
       -- that references the table with memory changed
       -- (may be empty).
-      for _, heap_chunk in pairs(event.primary) do
-        local ev_line = humanize.describe_location(symbols, heap_chunk.loc)
+      for id, heap_chunk in pairs(event.primary) do
+        local ev_line = id
 
         if (heap_chunk.alloced > 0) then
           dheap[ev_line].dbytes = dheap[ev_line].dbytes + heap_chunk.alloced
-- 
2.32.0



More information about the Tarantool-patches mailing list