Refactoring to determine the page size
This commit is contained in:
parent
2c09e21ae5
commit
8a1083cf4b
@ -104,6 +104,13 @@ THIS PROGRAM COMES WITH NO WARRANTY
|
|||||||
/* empty - used to show sections for manually triggered OOMs */
|
/* empty - used to show sections for manually triggered OOMs */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.js-pagesize-guessed--show {
|
||||||
|
/* empty - used to show if the page size is guessed */
|
||||||
|
}
|
||||||
|
.js-pagesize-determined--show {
|
||||||
|
/* empty - used to show if the page size is determined */
|
||||||
|
}
|
||||||
|
|
||||||
.js-pstable_sort_col0 {
|
.js-pstable_sort_col0 {
|
||||||
/* empty - used to sort process table */
|
/* empty - used to sort process table */
|
||||||
}
|
}
|
||||||
@ -871,7 +878,14 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Page size</td>
|
<td>Page size</td>
|
||||||
<td class="page_size_kb text--align-right"></td>
|
<td class="page_size_kb text--align-right"></td>
|
||||||
<td>Guessed</td>
|
<td>
|
||||||
|
<span class="js-text--default-hide js-pagesize-determined--show">
|
||||||
|
Extracted from DMA zone buddyinfo
|
||||||
|
</span>
|
||||||
|
<span class="js-text--default-hide js-pagesize-guessed--show">
|
||||||
|
Guessed
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
@ -2799,6 +2799,9 @@ class OOMAnalyser:
|
|||||||
)
|
)
|
||||||
"""RE to extract free memory chunks of a memor zone"""
|
"""RE to extract free memory chunks of a memor zone"""
|
||||||
|
|
||||||
|
REC_PAGE_SIZE = re.compile("Node 0 DMA: \d+\*(?P<page_size>\d+)kB")
|
||||||
|
"""RE to extract the page size from buddyinfo DMA zone"""
|
||||||
|
|
||||||
REC_WATERMARK = re.compile(
|
REC_WATERMARK = re.compile(
|
||||||
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal) "
|
"Node (?P<node>\d+) (?P<zone>DMA|DMA32|Normal) "
|
||||||
"free:(?P<free>\d+)kB "
|
"free:(?P<free>\d+)kB "
|
||||||
@ -3018,11 +3021,23 @@ class OOMAnalyser:
|
|||||||
call_trace += "{}\n".format(line.strip())
|
call_trace += "{}\n".format(line.strip())
|
||||||
self.oom_result.details["call_trace"] = call_trace
|
self.oom_result.details["call_trace"] = call_trace
|
||||||
|
|
||||||
|
self._extract_page_size()
|
||||||
self._extract_pstable()
|
self._extract_pstable()
|
||||||
self._extract_gpf_mask()
|
self._extract_gpf_mask()
|
||||||
self._extract_buddyinfo()
|
self._extract_buddyinfo()
|
||||||
self._extract_watermarks()
|
self._extract_watermarks()
|
||||||
|
|
||||||
|
def _extract_page_size(self):
|
||||||
|
"""Extract page size from buddyinfo DMZ zone"""
|
||||||
|
match = self.REC_PAGE_SIZE.search(self.oom_entity.text)
|
||||||
|
if match:
|
||||||
|
self.oom_result.details["page_size_kb"] = int(match.group("page_size"))
|
||||||
|
self.oom_result.details["_page_size_guessed"] = False
|
||||||
|
else:
|
||||||
|
# educated guess
|
||||||
|
self.oom_result.details["page_size_kb"] = 4
|
||||||
|
self.oom_result.details["_page_size_guessed"] = True
|
||||||
|
|
||||||
def _extract_pstable(self):
|
def _extract_pstable(self):
|
||||||
"""Extract process table"""
|
"""Extract process table"""
|
||||||
self.oom_result.details["_pstable"] = {}
|
self.oom_result.details["_pstable"] = {}
|
||||||
@ -3049,10 +3064,8 @@ class OOMAnalyser:
|
|||||||
This function fills:
|
This function fills:
|
||||||
* OOMResult.buddyinfo with [<zone>][<order>][<node>] = <number of free chunks>
|
* OOMResult.buddyinfo with [<zone>][<order>][<node>] = <number of free chunks>
|
||||||
* OOMResult.buddyinfo with [zone]["total_free_kb_per_node"][node] = int(total_free_kb_per_node)
|
* OOMResult.buddyinfo with [zone]["total_free_kb_per_node"][node] = int(total_free_kb_per_node)
|
||||||
* OOMResult.details["_buddyinfo_pagesize_kb"] with the extracted page size
|
|
||||||
"""
|
"""
|
||||||
self.oom_result.buddyinfo = {}
|
self.oom_result.buddyinfo = {}
|
||||||
self.oom_result.details["_buddyinfo_pagesize_kb"] = None
|
|
||||||
buddy_info = self.oom_result.buddyinfo
|
buddy_info = self.oom_result.buddyinfo
|
||||||
self.oom_entity.find_text(self.oom_result.kconfig.zoneinfo_start)
|
self.oom_entity.find_text(self.oom_result.kconfig.zoneinfo_start)
|
||||||
|
|
||||||
@ -3095,11 +3108,6 @@ class OOMAnalyser:
|
|||||||
node
|
node
|
||||||
]
|
]
|
||||||
|
|
||||||
if not self.oom_result.details["_buddyinfo_pagesize_kb"] and order == 0:
|
|
||||||
size = element.split("*")[1]
|
|
||||||
size = size[:-2] # strip "kB"
|
|
||||||
self.oom_result.details["_buddyinfo_pagesize_kb"] = int(size)
|
|
||||||
|
|
||||||
# MAX_ORDER is actually maximum order plus one. For example,
|
# MAX_ORDER is actually maximum order plus one. For example,
|
||||||
# a value of 11 means that the largest free memory block is 2^10 pages.
|
# a value of 11 means that the largest free memory block is 2^10 pages.
|
||||||
# __pragma__ ('jsiter')
|
# __pragma__ ('jsiter')
|
||||||
@ -3352,7 +3360,6 @@ class OOMAnalyser:
|
|||||||
highest_zoneidx = self.oom_result.kconfig.ZONE_TYPES.index(zone)
|
highest_zoneidx = self.oom_result.kconfig.ZONE_TYPES.index(zone)
|
||||||
lowmem_reserve = watermark_info[zone][node]["lowmem_reserve"]
|
lowmem_reserve = watermark_info[zone][node]["lowmem_reserve"]
|
||||||
min_kb = watermark_info[zone][node]["low"]
|
min_kb = watermark_info[zone][node]["low"]
|
||||||
page_size = self.oom_result.details["_buddyinfo_pagesize_kb"]
|
|
||||||
|
|
||||||
# reduce minimum watermark for high priority calls
|
# reduce minimum watermark for high priority calls
|
||||||
# ALLOC_HIGH == __GFP_HIGH
|
# ALLOC_HIGH == __GFP_HIGH
|
||||||
@ -3363,7 +3370,13 @@ class OOMAnalyser:
|
|||||||
|
|
||||||
# check watermarks, if these are not met, then a high-order request also
|
# check watermarks, if these are not met, then a high-order request also
|
||||||
# cannot go ahead even if a suitable page happened to be free.
|
# cannot go ahead even if a suitable page happened to be free.
|
||||||
if free_kb <= (min_kb + (lowmem_reserve[highest_zoneidx] * page_size)):
|
if free_kb <= (
|
||||||
|
min_kb
|
||||||
|
+ (
|
||||||
|
lowmem_reserve[highest_zoneidx]
|
||||||
|
* self.oom_result.details["page_size_kb"]
|
||||||
|
)
|
||||||
|
):
|
||||||
self.oom_result.mem_alloc_failure = (
|
self.oom_result.mem_alloc_failure = (
|
||||||
OOMMemoryAllocFailureType.failed_below_low_watermark
|
OOMMemoryAllocFailureType.failed_below_low_watermark
|
||||||
)
|
)
|
||||||
@ -3515,9 +3528,6 @@ class OOMAnalyser:
|
|||||||
dist = "Ubuntu"
|
dist = "Ubuntu"
|
||||||
self.oom_result.details["dist"] = dist
|
self.oom_result.details["dist"] = dist
|
||||||
|
|
||||||
# educated guess
|
|
||||||
self.oom_result.details["page_size_kb"] = 4
|
|
||||||
|
|
||||||
def _calc_from_oom_details(self):
|
def _calc_from_oom_details(self):
|
||||||
"""
|
"""
|
||||||
Calculate values from already extracted details
|
Calculate values from already extracted details
|
||||||
@ -4404,6 +4414,7 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
|||||||
self._show_ram_usage()
|
self._show_ram_usage()
|
||||||
self._show_alloc_failure()
|
self._show_alloc_failure()
|
||||||
self._show_memory_fragmentation()
|
self._show_memory_fragmentation()
|
||||||
|
self._show_page_size()
|
||||||
|
|
||||||
# generate process table
|
# generate process table
|
||||||
self._show_pstable()
|
self._show_pstable()
|
||||||
@ -4446,6 +4457,15 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
|||||||
else:
|
else:
|
||||||
show_elements(".js-memory-no-heavy-fragmentation--show")
|
show_elements(".js-memory-no-heavy-fragmentation--show")
|
||||||
|
|
||||||
|
def _show_page_size(self):
|
||||||
|
"""Show page size"""
|
||||||
|
if self.oom_result.details.get("_page_size_guessed", True):
|
||||||
|
hide_elements(".js-pagesize-determined--show")
|
||||||
|
show_elements(".js-pagesize-guessed--show")
|
||||||
|
else:
|
||||||
|
show_elements(".js-pagesize-determined--show")
|
||||||
|
hide_elements(".js-pagesize-guessed--show")
|
||||||
|
|
||||||
def _show_ram_usage(self):
|
def _show_ram_usage(self):
|
||||||
"""Generate RAM usage diagram"""
|
"""Generate RAM usage diagram"""
|
||||||
ram_title_attr = (
|
ram_title_attr = (
|
||||||
|
19
test.py
19
test.py
@ -1049,6 +1049,25 @@ Hardware name: HP ProLiant DL385 G7, BIOS A18 12/08/2012
|
|||||||
% (node, zone),
|
% (node, zone),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_013_page_size(self):
|
||||||
|
"""Test determination of the page size"""
|
||||||
|
oom = OOMAnalyser.OOMEntity(OOMAnalyser.OOMDisplay.example_rhel7)
|
||||||
|
analyser = OOMAnalyser.OOMAnalyser(oom)
|
||||||
|
success = analyser.analyse()
|
||||||
|
self.assertTrue(success, "OOM analysis failed")
|
||||||
|
|
||||||
|
page_size_kb = analyser.oom_result.details["page_size_kb"]
|
||||||
|
self.assertEqual(
|
||||||
|
page_size_kb,
|
||||||
|
4,
|
||||||
|
"Unexpected page size (got %s, expect: 4)" % page_size_kb,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
analyser.oom_result.details["_page_size_guessed"],
|
||||||
|
False,
|
||||||
|
"Page size guessed and not determinated",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
Loading…
Reference in New Issue
Block a user