-
Notifications
You must be signed in to change notification settings - Fork 11.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb] Speed up FindInMemory tests #111951
[lldb] Speed up FindInMemory tests #111951
Conversation
@llvm/pr-subscribers-lldb Author: Igor Kudrin (igorkudrin) ChangesA memory region can be relatively large. Searching for a value in the entire region is time-consuming, especially when running tests against a remote target, because the memory data is transferred in small chunks over a relatively slow GDB remote protocol. The patch limits the address range to be searched to 2K, which seems sufficient for these tests. In my setup, for local runs, these tests now take half the time they did before the patch. For a remote target, the improvement is even more significant. Full diff: https://github.com/llvm/llvm-project/pull/111951.diff 3 Files Affected:
diff --git a/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py b/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py
index 9ab4619b1f8f4f..04e807c5c6201d 100644
--- a/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py
+++ b/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py
@@ -55,7 +55,7 @@ def test_find_in_memory_ok(self):
error = lldb.SBError()
addr = self.process.FindInMemory(
SINGLE_INSTANCE_PATTERN_STACK,
- GetStackRange(self),
+ GetStackRange(self, True),
1,
error,
)
@@ -70,7 +70,7 @@ def test_find_in_memory_double_instance_ok(self):
error = lldb.SBError()
addr = self.process.FindInMemory(
DOUBLE_INSTANCE_PATTERN_HEAP,
- GetHeapRanges(self)[0],
+ GetHeapRanges(self, True)[0],
1,
error,
)
@@ -86,7 +86,7 @@ def test_find_in_memory_invalid_alignment(self):
error = lldb.SBError()
addr = self.process.FindInMemory(
SINGLE_INSTANCE_PATTERN_STACK,
- GetStackRange(self),
+ GetStackRange(self, True),
0,
error,
)
@@ -118,7 +118,7 @@ def test_find_in_memory_invalid_buffer(self):
error = lldb.SBError()
addr = self.process.FindInMemory(
"",
- GetStackRange(self),
+ GetStackRange(self, True),
1,
error,
)
@@ -131,7 +131,7 @@ def test_find_in_memory_unaligned(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
error = lldb.SBError()
- range = GetAlignedRange(self)
+ range = GetAlignedRange(self, True)
# First we make sure the pattern is found with alignment 1
addr = self.process.FindInMemory(
diff --git a/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py b/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py
index 31bc0e99f4914f..895c527430f218 100644
--- a/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py
+++ b/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py
@@ -30,7 +30,7 @@ def test_find_ranges_in_memory_two_matches(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetHeapRanges(self)
+ addr_ranges = GetHeapRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
DOUBLE_INSTANCE_PATTERN_HEAP,
@@ -48,7 +48,7 @@ def test_find_ranges_in_memory_one_match(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetStackRanges(self)
+ addr_ranges = GetStackRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
SINGLE_INSTANCE_PATTERN_STACK,
@@ -66,7 +66,7 @@ def test_find_ranges_in_memory_one_match_multiple_ranges(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetRanges(self)
+ addr_ranges = GetRanges(self, True)
addr_ranges.Append(lldb.SBAddressRange())
self.assertGreater(addr_ranges.GetSize(), 2)
error = lldb.SBError()
@@ -86,7 +86,7 @@ def test_find_ranges_in_memory_one_match_max(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetHeapRanges(self)
+ addr_ranges = GetHeapRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
DOUBLE_INSTANCE_PATTERN_HEAP,
@@ -104,7 +104,7 @@ def test_find_ranges_in_memory_invalid_alignment(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetHeapRanges(self)
+ addr_ranges = GetHeapRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
DOUBLE_INSTANCE_PATTERN_HEAP,
@@ -160,7 +160,7 @@ def test_find_ranges_in_memory_invalid_buffer(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetHeapRanges(self)
+ addr_ranges = GetHeapRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
"",
@@ -178,7 +178,7 @@ def test_find_ranges_in_memory_invalid_max_matches(self):
self.assertTrue(self.process, PROCESS_IS_VALID)
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- addr_ranges = GetHeapRanges(self)
+ addr_ranges = GetHeapRanges(self, True)
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
DOUBLE_INSTANCE_PATTERN_HEAP,
@@ -197,7 +197,7 @@ def test_find_in_memory_unaligned(self):
self.assertState(self.process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
addr_ranges = lldb.SBAddressRangeList()
- addr_ranges.Append(GetAlignedRange(self))
+ addr_ranges.Append(GetAlignedRange(self, True))
error = lldb.SBError()
matches = self.process.FindRangesInMemory(
diff --git a/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py b/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
index 810fb9fee38615..6c77b3e911c5d5 100644
--- a/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
+++ b/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
@@ -6,27 +6,30 @@
UNALIGNED_INSTANCE_PATTERN_HEAP = ALIGNED_INSTANCE_PATTERN_HEAP[1:]
-def GetAlignedRange(test_base):
+def GetAlignedRange(test_base, shrink=False):
frame = test_base.thread.GetSelectedFrame()
ex = frame.EvaluateExpression("aligned_string_ptr")
test_base.assertTrue(ex.IsValid())
- return GetRangeFromAddrValue(test_base, ex)
+ return GetRangeFromAddrValue(test_base, ex, shrink)
-def GetStackRange(test_base):
+def GetStackRange(test_base, shrink=False):
frame = test_base.thread.GetSelectedFrame()
ex = frame.EvaluateExpression("&stack_pointer")
test_base.assertTrue(ex.IsValid())
- return GetRangeFromAddrValue(test_base, ex)
+ return GetRangeFromAddrValue(test_base, ex, shrink)
-def GetStackRanges(test_base):
+def GetStackRanges(test_base, shrink=False):
addr_ranges = lldb.SBAddressRangeList()
addr_ranges.Append(GetStackRange(test_base))
return addr_ranges
-def GetRangeFromAddrValue(test_base, addr):
+def GetRangeFromAddrValue(test_base, addr, shrink=False):
+ """ Return the address range containing 'addr'.
+ If 'shrink' is True, the size of the region will not exceed 2K.
+ """
region = lldb.SBMemoryRegionInfo()
test_base.assertTrue(
test_base.process.GetMemoryRegionInfo(
@@ -36,38 +39,49 @@ def GetRangeFromAddrValue(test_base, addr):
test_base.assertTrue(region.IsReadable())
test_base.assertFalse(region.IsExecutable())
+
+ base = region.GetRegionBase()
+ end = region.GetRegionEnd()
- address_start = lldb.SBAddress(region.GetRegionBase(), test_base.target)
- stack_size = region.GetRegionEnd() - region.GetRegionBase()
- return lldb.SBAddressRange(address_start, stack_size)
+ if shrink:
+ addr2 = addr.GetValueAsUnsigned()
+ addr2 -= addr2 % 512
+ base = max(base, addr2 - 1024)
+ end = min(end, addr2 + 1024)
+ start = lldb.SBAddress(base, test_base.target)
+ size = end - base
-def IsWithinRange(addr, range, target):
+ return lldb.SBAddressRange(start, size)
+
+
+def IsWithinRange(addr, size, range, target):
start_addr = range.GetBaseAddress().GetLoadAddress(target)
end_addr = start_addr + range.GetByteSize()
addr = addr.GetValueAsUnsigned()
- return addr >= start_addr and addr < end_addr
+ return addr >= start_addr and addr + size <= end_addr
-def GetHeapRanges(test_base):
+def GetHeapRanges(test_base, shrink=False):
frame = test_base.thread.GetSelectedFrame()
ex = frame.EvaluateExpression("heap_pointer1")
test_base.assertTrue(ex.IsValid())
- range = GetRangeFromAddrValue(test_base, ex)
+ range = GetRangeFromAddrValue(test_base, ex, shrink)
addr_ranges = lldb.SBAddressRangeList()
addr_ranges.Append(range)
ex = frame.EvaluateExpression("heap_pointer2")
test_base.assertTrue(ex.IsValid())
- if not IsWithinRange(ex, addr_ranges[0], test_base.target):
- addr_ranges.Append(GetRangeFromAddrValue(test_base, ex))
+ size = len(DOUBLE_INSTANCE_PATTERN_HEAP)
+ if not IsWithinRange(ex, size, addr_ranges[0], test_base.target):
+ addr_ranges.Append(GetRangeFromAddrValue(test_base, ex, shrink))
return addr_ranges
-def GetRanges(test_base):
- ranges = GetHeapRanges(test_base)
- ranges.Append(GetStackRanges(test_base))
+def GetRanges(test_base, shrink=False):
+ ranges = GetHeapRanges(test_base, shrink)
+ ranges.Append(GetStackRanges(test_base, shrink))
return ranges
|
✅ With the latest revision this PR passed the Python code formatter. |
A memory region can be relatively large. Searching for a value in the entire region is time-consuming, especially when running tests against a remote target, because the memory data is transferred in small chunks over a relatively slow GDB Remote Protocol. The patch limits the address range to be searched to 2K, which seems sufficient for these tests. In my setup, for local runs, these tests now take half the time they did before the patch. For a remote target, the improvement is even more significant.
6ea1173
to
e027444
Compare
addr_ranges = lldb.SBAddressRangeList() | ||
addr_ranges.Append(GetStackRange(test_base)) | ||
return addr_ranges | ||
|
||
|
||
def GetRangeFromAddrValue(test_base, addr): | ||
def GetRangeFromAddrValue(test_base, addr, shrink=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since these are only used for testing, why not remove the shrink
parameter and always keep the memory region below 2K?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all tests do actual searches. For example, test_check_stack_pointer()
in TestFindInMemory.py
checks that ranges for two different stack pointers are the same.
A memory region can be relatively large. Searching for a value in the entire region is time-consuming, especially when running tests against a remote target, because the memory data is transferred in small chunks over a relatively slow GDB Remote Protocol. The patch limits the address range to be searched to 2K, which seems sufficient for these tests. In my setup, for local runs, these tests now take half the time they did before the patch. For a remote target, the improvement is even more significant.