Skip to content

Commit 101c73e

Browse files
committed
Skip the cache of DWARFInfo and CU.
Add DWARFInfo.skip_cache() and DWARFInfo.enable_cache() to give users the ability of controlling cache. For the case of parsing the DWARF of a large binary, we may want to skip the cache to release the memory ASAP, avoiding extra CPU cycles on maintaining a cache. One of my use cases is to extract types, functions, and call sites from the DWARF of a Linux kernel image. With caches, it takes about 573 seconds to go through all DIEs. Skipping caches reduces time to 448 seconds. It is about 27% faster. When going through every DIEs sequentially, cache doesn't help use at all.
1 parent c359508 commit 101c73e

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

elftools/dwarf/compileunit.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ def _get_cached_DIE(self, offset):
226226
# the top DIE and obtain a reference to its stream.
227227
top_die_stream = self.get_top_DIE().stream
228228

229+
if self.dwarfinfo._skip_cache:
230+
return DIE(cu=self, stream=top_die_stream, offset=offset)
231+
229232
# `offset` is the offset in the stream of the DIE we want to return.
230233
# The map is maintined as a parallel array to the list. We call
231234
# bisect each time to ensure new DIEs are inserted in the correct

elftools/dwarf/dwarfinfo.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ def __init__(self,
134134
self._cu_cache = []
135135
self._cu_offsets_map = []
136136

137+
self._skip_cache = False
138+
137139
@property
138140
def has_debug_info(self):
139141
""" Return whether this contains debug information.
@@ -430,6 +432,10 @@ def _cached_CU_at_offset(self, offset):
430432
431433
See get_CU_at().
432434
"""
435+
if self._skip_cache:
436+
cu = self._parse_CU_at_offset(offset)
437+
return cu
438+
433439
# Find the insert point for the requested offset. With bisect_right,
434440
# if this entry is present in the cache it will be the prior entry.
435441
i = bisect_right(self._cu_offsets_map, offset)
@@ -575,3 +581,10 @@ def parse_debugsupinfo(self):
575581
return suplink.sup_filename
576582
return None
577583

584+
def skip_cache(self):
585+
self._skip_cache = True
586+
pass
587+
588+
def enable_cache(self):
589+
self._skip_cache = False
590+
pass

0 commit comments

Comments
 (0)