xref: /spdk/scripts/dpdk_mem_info.py (revision 2e1c5a722da9ce16ab8b327547d042a81148370a)
10e9727dbSSeth Howell#!/usr/bin/env python3
217538bdcSpaul luse#  SPDX-License-Identifier: BSD-3-Clause
317538bdcSpaul luse#  Copyright (C) 2019 Intel Corporation
417538bdcSpaul luse#  All rights reserved.
517538bdcSpaul luse#
60e9727dbSSeth Howell
70e9727dbSSeth Howellimport argparse
80e9727dbSSeth Howellimport os
90e9727dbSSeth Howellfrom enum import Enum
100e9727dbSSeth Howell
110e9727dbSSeth Howell
120e9727dbSSeth Howellclass memory:
130e9727dbSSeth Howell    def __init__(self, size):
140e9727dbSSeth Howell        self.size = size
150e9727dbSSeth Howell        self.heaps = []
160e9727dbSSeth Howell        self.mempools = []
170e9727dbSSeth Howell        self.memzones = []
180e9727dbSSeth Howell
190e9727dbSSeth Howell    def get_size(self):
200e9727dbSSeth Howell        return self.size
210e9727dbSSeth Howell
220e9727dbSSeth Howell    def add_mempool(self, pool):
230e9727dbSSeth Howell        self.mempools.append(pool)
240e9727dbSSeth Howell
250e9727dbSSeth Howell    def add_memzone(self, zone):
260e9727dbSSeth Howell        self.memzones.append(zone)
270e9727dbSSeth Howell
280e9727dbSSeth Howell    def add_heap(self, heap):
290e9727dbSSeth Howell        self.heaps.append(heap)
300e9727dbSSeth Howell
310e9727dbSSeth Howell    def get_total_heap_size(self):
320e9727dbSSeth Howell        size = 0
330e9727dbSSeth Howell        for heap in self.heaps:
340e9727dbSSeth Howell            size = size + heap.size
350e9727dbSSeth Howell        return size
360e9727dbSSeth Howell
370e9727dbSSeth Howell    def get_total_mempool_size(self):
380e9727dbSSeth Howell        size = 0
390e9727dbSSeth Howell        for pool in self.mempools:
400e9727dbSSeth Howell            size = size + pool.get_memzone_size_sum()
410e9727dbSSeth Howell        return size
420e9727dbSSeth Howell
430e9727dbSSeth Howell    def get_total_memzone_size(self):
440e9727dbSSeth Howell        size = 0
450e9727dbSSeth Howell        for zone in self.memzones:
460e9727dbSSeth Howell            size = size + zone.size
470e9727dbSSeth Howell        return size
480e9727dbSSeth Howell
490e9727dbSSeth Howell    def print_summary(self):
500e9727dbSSeth Howell        print("DPDK memory size {} in {} heap(s)"
510e9727dbSSeth Howell              .format(B_to_MiB(self.size), len(self.heaps)))
520e9727dbSSeth Howell        print("{} heaps totaling size {}".format(len(self.heaps), B_to_MiB(self.get_total_heap_size())))
530e9727dbSSeth Howell        for x in sorted(self.heaps, key=lambda x: x.size, reverse=True):
540e9727dbSSeth Howell            x.print_summary('  ')
550e9727dbSSeth Howell        print("end heaps----------")
560e9727dbSSeth Howell        print("{} mempools totaling size {}".format(len(self.mempools), B_to_MiB(self.get_total_mempool_size())))
570e9727dbSSeth Howell        for x in sorted(self.mempools, key=lambda x: x.get_memzone_size_sum(), reverse=True):
580e9727dbSSeth Howell            x.print_summary('  ')
590e9727dbSSeth Howell        print("end mempools-------")
600e9727dbSSeth Howell        print("{} memzones totaling size {}".format(len(self.memzones), B_to_MiB(self.get_total_memzone_size())))
610e9727dbSSeth Howell        for x in sorted(self.memzones, key=lambda x: x.size, reverse=True):
620e9727dbSSeth Howell            x.print_summary('  ')
630e9727dbSSeth Howell        print("end memzones-------")
640e9727dbSSeth Howell
650e9727dbSSeth Howell    def print_heap_summary(self, heap_id):
660e9727dbSSeth Howell        for heap in self.heaps:
670e9727dbSSeth Howell            if heap_id == heap.id:
680e9727dbSSeth Howell                heap.print_detailed_stats()
690e9727dbSSeth Howell                break
700e9727dbSSeth Howell        else:
710e9727dbSSeth Howell            print("heap id {} is invalid. please see the summary for valid heaps.\n".format(heap_id))
720e9727dbSSeth Howell
730e9727dbSSeth Howell    def print_mempool_summary(self, name):
740e9727dbSSeth Howell        for pool in self.mempools:
750e9727dbSSeth Howell            if name == pool.name:
760e9727dbSSeth Howell                pool.print_detailed_stats()
770e9727dbSSeth Howell                break
780e9727dbSSeth Howell        else:
790e9727dbSSeth Howell            print("mempool name {} is invalid. please see the summary for valid mempools.\n".format(name))
800e9727dbSSeth Howell
810e9727dbSSeth Howell    def print_memzone_summary(self, name):
820e9727dbSSeth Howell        for zone in self.memzones:
830e9727dbSSeth Howell            if name == zone.name:
840e9727dbSSeth Howell                zone.print_detailed_stats("")
850e9727dbSSeth Howell                break
860e9727dbSSeth Howell        else:
870e9727dbSSeth Howell            print("memzone name {} is invalid. please see the summary for valid memzone.\n".format(name))
880e9727dbSSeth Howell
890e9727dbSSeth Howell    def associate_heap_elements_and_memzones(self):
900e9727dbSSeth Howell        for zone in self.memzones:
910e9727dbSSeth Howell            for heap_obj in self.heaps:
920e9727dbSSeth Howell                for element in heap_obj.busy_malloc_elements:
930e9727dbSSeth Howell                    if element.check_memzone_compatibility(zone):
940e9727dbSSeth Howell                        heap_obj.busy_memzone_elements.append(element)
950e9727dbSSeth Howell                        heap_obj.busy_malloc_elements.remove(element)
960e9727dbSSeth Howell
970e9727dbSSeth Howell    def associate_memzones_and_mempools(self):
980e9727dbSSeth Howell        for pool in self.mempools:
990e9727dbSSeth Howell            for zone in self.memzones:
1000e9727dbSSeth Howell                if pool.name in zone.name:
1010e9727dbSSeth Howell                    pool.add_memzone(zone)
1020e9727dbSSeth Howell
1030e9727dbSSeth Howell        for pool in self.mempools:
1040e9727dbSSeth Howell            for zone in pool.memzones:
1050e9727dbSSeth Howell                if zone in self.memzones:
1060e9727dbSSeth Howell                    self.memzones.remove(zone)
1070e9727dbSSeth Howell
1080e9727dbSSeth Howell
1090e9727dbSSeth Howellclass heap_elem_status(Enum):
1100e9727dbSSeth Howell    FREE = 0
1110e9727dbSSeth Howell    BUSY = 1
1120e9727dbSSeth Howell
1130e9727dbSSeth Howell
1140e9727dbSSeth Howellclass heap_element:
1150e9727dbSSeth Howell    def __init__(self, size, status, addr):
1160e9727dbSSeth Howell        self.status = status
1170e9727dbSSeth Howell        self.size = size
1180e9727dbSSeth Howell        self.addr = addr
1190e9727dbSSeth Howell        self.memzone = None
1200e9727dbSSeth Howell
1210e9727dbSSeth Howell    def print_summary(self, header):
1220e9727dbSSeth Howell        print("{}element at address: {} with size: {:>15}".format(header, hex(self.addr), B_to_MiB(self.size)))
1230e9727dbSSeth Howell
1240e9727dbSSeth Howell    def check_memzone_compatibility(self, memzone):
1250e9727dbSSeth Howell        ele_fini_addr = self.addr + self.size
1260e9727dbSSeth Howell        memzone_fini_addr = memzone.address + memzone.size
1270e9727dbSSeth Howell        if (self.addr <= memzone.address and ele_fini_addr >= memzone_fini_addr):
1280e9727dbSSeth Howell            self.memzone = memzone
1290e9727dbSSeth Howell            return True
1300e9727dbSSeth Howell        return False
1310e9727dbSSeth Howell
1320e9727dbSSeth Howell
1330e9727dbSSeth Howellclass heap:
1340e9727dbSSeth Howell    def __init__(self, id, size, num_allocations):
1350e9727dbSSeth Howell        self.id = id
1360e9727dbSSeth Howell        self.size = size
1370e9727dbSSeth Howell        self.num_allocations = num_allocations
1380e9727dbSSeth Howell        self.free_elements = []
1390e9727dbSSeth Howell        self.busy_malloc_elements = []
1400e9727dbSSeth Howell        self.busy_memzone_elements = []
1410e9727dbSSeth Howell
1420e9727dbSSeth Howell    def add_element(self, element):
1430e9727dbSSeth Howell        if element.status == heap_elem_status.FREE:
1440e9727dbSSeth Howell            self.free_elements.append(element)
1450e9727dbSSeth Howell        else:
1460e9727dbSSeth Howell            self.busy_malloc_elements.append(element)
1470e9727dbSSeth Howell
1480e9727dbSSeth Howell    def print_element_stats(self, list_to_print, list_type, header):
1490e9727dbSSeth Howell        print("{}list of {} elements. size: {}".format(header, list_type, B_to_MiB(self.get_element_size(list_to_print))))
1500e9727dbSSeth Howell        for x in sorted(list_to_print, key=lambda x: x.size, reverse=True):
1510e9727dbSSeth Howell            x.print_summary("{}  ".format(header))
1520e9727dbSSeth Howell            if x.memzone is not None:
1530e9727dbSSeth Howell                x.memzone.print_summary("    {}associated memzone info: ".format(header))
1540e9727dbSSeth Howell
1550e9727dbSSeth Howell    def get_element_size(self, list_to_check):
1560e9727dbSSeth Howell        size = 0
1570e9727dbSSeth Howell        for element in list_to_check:
1580e9727dbSSeth Howell            size = size + element.size
1590e9727dbSSeth Howell        return size
1600e9727dbSSeth Howell
1610e9727dbSSeth Howell    def print_summary(self, header):
1620e9727dbSSeth Howell        print("{}size: {:>15} heap id: {}".format(header, B_to_MiB(self.size), self.id))
1630e9727dbSSeth Howell
1640e9727dbSSeth Howell    def print_detailed_stats(self):
1650e9727dbSSeth Howell        print("heap id: {} total size: {} number of busy elements: {} number of free elements: {}"
1660e9727dbSSeth Howell              .format(self.id, B_to_MiB(self.size), len(self.busy_malloc_elements), len(self.free_elements)))
1670e9727dbSSeth Howell        self.print_element_stats(self.free_elements, "free", "  ")
1680e9727dbSSeth Howell        self.print_element_stats(self.busy_malloc_elements, "standard malloc", "  ")
1690e9727dbSSeth Howell        self.print_element_stats(self.busy_memzone_elements, "memzone associated", "  ")
1700e9727dbSSeth Howell
1710e9727dbSSeth Howell
1720e9727dbSSeth Howellclass mempool:
1730e9727dbSSeth Howell    def __init__(self, name, num_objs, num_populated_objs, obj_size):
1740e9727dbSSeth Howell        self.name = name
1750e9727dbSSeth Howell        self.num_objs = num_objs
1760e9727dbSSeth Howell        self.num_populated_objs = num_populated_objs
1770e9727dbSSeth Howell        self.obj_size = obj_size
1780e9727dbSSeth Howell        self.memzones = []
1790e9727dbSSeth Howell
1800e9727dbSSeth Howell    def add_memzone(self, memzone):
1810e9727dbSSeth Howell        self.memzones.append(memzone)
1820e9727dbSSeth Howell
1830e9727dbSSeth Howell    def get_memzone_size_sum(self):
1840e9727dbSSeth Howell        size = 0
1850e9727dbSSeth Howell        for zone in self.memzones:
1860e9727dbSSeth Howell            size = size + zone.size
1870e9727dbSSeth Howell        return size
1880e9727dbSSeth Howell
1890e9727dbSSeth Howell    def print_summary(self, header):
1900e9727dbSSeth Howell        print("{}size: {:>15} name: {}"
1910e9727dbSSeth Howell              .format(header, B_to_MiB(self.get_memzone_size_sum()), self.name))
1920e9727dbSSeth Howell
1930e9727dbSSeth Howell    def print_detailed_stats(self):
1940e9727dbSSeth Howell        print("size: {:>15} name: {} comprised of {} memzone(s):"
1950e9727dbSSeth Howell              .format(B_to_MiB(self.get_memzone_size_sum()), self.name, len(self.memzones)))
1960e9727dbSSeth Howell        for x in sorted(self.memzones, key=lambda x: x.size, reverse=True):
1970e9727dbSSeth Howell            x.print_detailed_stats("  ")
1980e9727dbSSeth Howell
1990e9727dbSSeth Howell
2000e9727dbSSeth Howellclass memzone:
2010e9727dbSSeth Howell    def __init__(self, name, size, address):
2020e9727dbSSeth Howell        self.name = name
2030e9727dbSSeth Howell        self.size = size
2040e9727dbSSeth Howell        self.address = address
2050e9727dbSSeth Howell        self.segments = []
2060e9727dbSSeth Howell
2070e9727dbSSeth Howell    def add_segment(self, segment):
2080e9727dbSSeth Howell        self.segments.append(segment)
2090e9727dbSSeth Howell
2100e9727dbSSeth Howell    def print_summary(self, header):
2110e9727dbSSeth Howell        print("{}size: {:>15} name: {}".format(header,  B_to_MiB(self.size), self.name))
2120e9727dbSSeth Howell
2130e9727dbSSeth Howell    def print_detailed_stats(self, header):
2140e9727dbSSeth Howell        self.print_summary(header)
2150e9727dbSSeth Howell        print("{}located at address {}".format(header, hex(self.address)))
2160e9727dbSSeth Howell        print("{}spanning {} segment(s):".format(header, len(self.segments)))
2170e9727dbSSeth Howell        for x in sorted(self.segments, key=lambda x: x.size, reverse=True):
2180e9727dbSSeth Howell            x.print_summary('  ')
2190e9727dbSSeth Howell
2200e9727dbSSeth Howell
2210e9727dbSSeth Howellclass segment:
2220e9727dbSSeth Howell    def __init__(self, size, address):
2230e9727dbSSeth Howell        self.size = size
2240e9727dbSSeth Howell        self.address = address
2250e9727dbSSeth Howell
2260e9727dbSSeth Howell    def print_summary(self, header):
2270e9727dbSSeth Howell        print("{}address: {} length: {:>15}".format(header, hex(self.address), B_to_MiB(self.size)))
2280e9727dbSSeth Howell
2290e9727dbSSeth Howell
2300e9727dbSSeth Howellclass parse_state(Enum):
2310e9727dbSSeth Howell    PARSE_MEMORY_SIZE = 0
2320e9727dbSSeth Howell    PARSE_MEMZONES = 1
2330e9727dbSSeth Howell    PARSE_MEMZONE_SEGMENTS = 2
2340e9727dbSSeth Howell    PARSE_MEMPOOLS = 3
2350e9727dbSSeth Howell    PARSE_MEMPOOL_INFO = 4
2360e9727dbSSeth Howell    PARSE_HEAPS = 5
2370e9727dbSSeth Howell    PARSE_HEAP_ELEMENTS = 6
2380e9727dbSSeth Howell
2390e9727dbSSeth Howell
2400e9727dbSSeth Howelldef B_to_MiB(raw_value):
2410e9727dbSSeth Howell    raw_value = raw_value / (1024.0 * 1024.0)
2420e9727dbSSeth Howell
2430e9727dbSSeth Howell    return "%6f %s" % (raw_value, "MiB")
2440e9727dbSSeth Howell
2450e9727dbSSeth Howell
2460e9727dbSSeth Howelldef parse_zone(line):
2470e9727dbSSeth Howell    zone, info = line.split(':', 1)
2480e9727dbSSeth Howell    name, length, addr, trash = info.split(',', 3)
2490e9727dbSSeth Howell
2500e9727dbSSeth Howell    trash, name = name.split(':', 1)
2510e9727dbSSeth Howell    name = name.replace("<", "")
2520e9727dbSSeth Howell    name = name.replace(">", "")
2530e9727dbSSeth Howell    trash, length = length.split(':', 1)
2540e9727dbSSeth Howell    trash, addr = addr.split(':', 1)
2550e9727dbSSeth Howell
2560e9727dbSSeth Howell    return memzone(name, int(length, 0), int(addr, 0))
2570e9727dbSSeth Howell
2580e9727dbSSeth Howell
2590e9727dbSSeth Howelldef parse_segment(line):
2600e9727dbSSeth Howell    trash, addr, iova, length, pagesz = line.split(':')
2610e9727dbSSeth Howell    addr, trash = addr.strip().split(' ')
2620e9727dbSSeth Howell    length, trash = length.strip().split(' ')
2630e9727dbSSeth Howell
2640e9727dbSSeth Howell    return segment(int(length, 0), int(addr, 0))
2650e9727dbSSeth Howell
2660e9727dbSSeth Howell
2670e9727dbSSeth Howelldef parse_mempool_name(line):
2680e9727dbSSeth Howell    name, addr = line.split('@')
2690e9727dbSSeth Howell    name = name.replace("<", "")
2700e9727dbSSeth Howell    name = name.replace(">", "")
271*2e1c5a72SJim Harris    trash, sep, name = name.partition(' ')
2720e9727dbSSeth Howell
2730e9727dbSSeth Howell    return name
2740e9727dbSSeth Howell
2750e9727dbSSeth Howell
2760e9727dbSSeth Howelldef parse_mem_stats(stat_path):
2770e9727dbSSeth Howell    state = parse_state.PARSE_MEMORY_SIZE
2780e9727dbSSeth Howell    with open(stat_path, "r") as stats:
2790e9727dbSSeth Howell
2800e9727dbSSeth Howell        line = stats.readline()
2810e9727dbSSeth Howell        while line != '':
2820e9727dbSSeth Howell            if state == parse_state.PARSE_MEMORY_SIZE:
2830e9727dbSSeth Howell                if "DPDK memory size" in line:
2840e9727dbSSeth Howell                    mem_size = int(line.replace("DPDK memory size ", ""))
2850e9727dbSSeth Howell                    memory_struct = memory(mem_size)
2860e9727dbSSeth Howell                    state = parse_state.PARSE_MEMZONES
2870e9727dbSSeth Howell                line = stats.readline()
2880e9727dbSSeth Howell
2890e9727dbSSeth Howell            if state == parse_state.PARSE_MEMZONES:
2900e9727dbSSeth Howell                if line.find("Zone") == 0:
2910e9727dbSSeth Howell                    zone = parse_zone(line)
29212aefaa0STomasz Zawadzki                    memory_struct.add_memzone(zone)
2930e9727dbSSeth Howell                    state = parse_state.PARSE_MEMZONE_SEGMENTS
2940e9727dbSSeth Howell                line = stats.readline()
2950e9727dbSSeth Howell
2960e9727dbSSeth Howell            if state == parse_state.PARSE_MEMZONE_SEGMENTS:
2970e9727dbSSeth Howell                if line.find("Zone") == 0:
2980e9727dbSSeth Howell                    state = parse_state.PARSE_MEMZONES
2990e9727dbSSeth Howell                    continue
3000e9727dbSSeth Howell                elif line.lstrip().find("addr:") == 0:
3010e9727dbSSeth Howell                    segment = parse_segment(line)
3020e9727dbSSeth Howell                    zone.add_segment(segment)
3030e9727dbSSeth Howell                elif "DPDK mempools." in line:
3040e9727dbSSeth Howell                    state = parse_state.PARSE_MEMPOOLS
3050e9727dbSSeth Howell                    continue
3060e9727dbSSeth Howell                line = stats.readline()
3070e9727dbSSeth Howell
3080e9727dbSSeth Howell            if state == parse_state.PARSE_MEMPOOLS:
3090e9727dbSSeth Howell                mempool_info = {}
3100e9727dbSSeth Howell                if line.find("mempool") == 0:
3110e9727dbSSeth Howell                    mempool_info['name'] = parse_mempool_name(line)
3120e9727dbSSeth Howell                    state = parse_state.PARSE_MEMPOOL_INFO
3130e9727dbSSeth Howell                line = stats.readline()
3140e9727dbSSeth Howell
3150e9727dbSSeth Howell            if state == parse_state.PARSE_MEMPOOL_INFO:
3160e9727dbSSeth Howell                if line.find("mempool") == 0:
3170e9727dbSSeth Howell                    try:
3180e9727dbSSeth Howell                        new_mempool = mempool(mempool_info['name'], int(mempool_info['size'], 0),
3190e9727dbSSeth Howell                                              int(mempool_info['populated_size'], 0), int(mempool_info['total_obj_size'], 0))
3200e9727dbSSeth Howell                        memory_struct.add_mempool(new_mempool)
3210e9727dbSSeth Howell                    except KeyError:
3220e9727dbSSeth Howell                        print("proper key values not provided for mempool.")
3230e9727dbSSeth Howell                    state = parse_state.PARSE_MEMPOOLS
3240e9727dbSSeth Howell                    continue
3250e9727dbSSeth Howell                elif "cache" in line:
3260e9727dbSSeth Howell                    pass
3270e9727dbSSeth Howell                elif "DPDK malloc stats." in line:
3280e9727dbSSeth Howell                    try:
3290e9727dbSSeth Howell                        new_mempool = mempool(mempool_info['name'], int(mempool_info['size'], 0),
3300e9727dbSSeth Howell                                              int(mempool_info['populated_size'], 0), int(mempool_info['total_obj_size'], 0))
3310e9727dbSSeth Howell                        memory_struct.add_mempool(new_mempool)
3320e9727dbSSeth Howell                    except KeyError:
3330e9727dbSSeth Howell                        print("proper key values not provided for mempool.")
3340e9727dbSSeth Howell                    while "DPDK malloc heaps." not in line:
3350e9727dbSSeth Howell                        line = stats.readline()
3360e9727dbSSeth Howell                    state = parse_state.PARSE_HEAPS
3370e9727dbSSeth Howell                else:
3380e9727dbSSeth Howell                    try:
3390e9727dbSSeth Howell                        field, value = line.strip().split('=')
3400e9727dbSSeth Howell                        mempool_info[field] = value
3410e9727dbSSeth Howell                    except Exception as e:
3420e9727dbSSeth Howell                        pass
3430e9727dbSSeth Howell                line = stats.readline()
3440e9727dbSSeth Howell
3450e9727dbSSeth Howell            if state == parse_state.PARSE_HEAPS:
3460e9727dbSSeth Howell                trash, heap_id = line.strip().split(':')
3470e9727dbSSeth Howell                line = stats.readline()
3480e9727dbSSeth Howell                trash, heap_size = line.split(':')
3490e9727dbSSeth Howell                line = stats.readline()
3500e9727dbSSeth Howell                trash, num_allocations = line.split(':')
3510e9727dbSSeth Howell                if int(heap_size, 0) == 0:
3520e9727dbSSeth Howell                    pass
3530e9727dbSSeth Howell                else:
3540e9727dbSSeth Howell                    new_heap = heap(heap_id.lstrip(), int(heap_size, 0), int(num_allocations, 0))
3550e9727dbSSeth Howell                    memory_struct.add_heap(new_heap)
3560e9727dbSSeth Howell                    state = parse_state.PARSE_HEAP_ELEMENTS
3570e9727dbSSeth Howell
3580e9727dbSSeth Howell                line = stats.readline()
3590e9727dbSSeth Howell
3600e9727dbSSeth Howell            if state == parse_state.PARSE_HEAP_ELEMENTS:
3610e9727dbSSeth Howell                if line.find("Heap id") == 0:
3620e9727dbSSeth Howell                    state = parse_state.PARSE_HEAPS
3630e9727dbSSeth Howell                    continue
3640e9727dbSSeth Howell                elif line.find("Malloc element at") == 0:
3650e9727dbSSeth Howell                    trash, address, status = line.rsplit(maxsplit=2)
3660e9727dbSSeth Howell                    line = stats.readline()
3670e9727dbSSeth Howell                    trash, length, trash = line.split(maxsplit=2)
3680e9727dbSSeth Howell                    line = stats.readline()
3690e9727dbSSeth Howell                    if "FREE" in status:
3700e9727dbSSeth Howell                        element = heap_element(int(length, 0), heap_elem_status.FREE, int(address, 0))
3710e9727dbSSeth Howell                    else:
3720e9727dbSSeth Howell                        element = heap_element(int(length, 0), heap_elem_status.BUSY, int(address, 0))
3730e9727dbSSeth Howell                    new_heap.add_element(element)
3740e9727dbSSeth Howell                line = stats.readline()
3750e9727dbSSeth Howell
3760e9727dbSSeth Howell    memory_struct.associate_heap_elements_and_memzones()
3770e9727dbSSeth Howell    memory_struct.associate_memzones_and_mempools()
3780e9727dbSSeth Howell    return memory_struct
3790e9727dbSSeth Howell
3800e9727dbSSeth Howell
3810e9727dbSSeth Howellif __name__ == "__main__":
3820e9727dbSSeth Howell    parser = argparse.ArgumentParser(description='Dumps memory stats for DPDK. If no arguments are provided, it dumps a general summary.')
3830e9727dbSSeth Howell    parser.add_argument('-f', dest="stats_file", help='path to a dpdk memory stats file.', default='/tmp/spdk_mem_dump.txt')
3840e9727dbSSeth Howell    parser.add_argument('-m', '--heap', dest="heap", help='Print detailed information about the given heap.', default=None)
3850e9727dbSSeth Howell    parser.add_argument('-p', '--mempool', dest="mempool", help='Print detailed information about the given mempool.', default=None)
3860e9727dbSSeth Howell    parser.add_argument('-z', '--memzone', dest="memzone", help='Print detailed information about the given memzone.', default=None)
3870e9727dbSSeth Howell
3880e9727dbSSeth Howell    args = parser.parse_args()
3890e9727dbSSeth Howell
3900e9727dbSSeth Howell    if not os.path.exists(args.stats_file):
3910e9727dbSSeth Howell        print("Error, specified stats file does not exist. Please make sure you have run the "
3920e9727dbSSeth Howell              "env_dpdk_get_mem_stats rpc on the spdk app you want to analyze.")
3930e9727dbSSeth Howell        exit(1)
3940e9727dbSSeth Howell
3950e9727dbSSeth Howell    mem_info = parse_mem_stats(args.stats_file)
3960e9727dbSSeth Howell
3970e9727dbSSeth Howell    summary = True
3980e9727dbSSeth Howell    if args.heap is not None:
3990e9727dbSSeth Howell        mem_info.print_heap_summary(args.heap)
4000e9727dbSSeth Howell        summary = False
4010e9727dbSSeth Howell    if args.mempool is not None:
4020e9727dbSSeth Howell        mem_info.print_mempool_summary(args.mempool)
4030e9727dbSSeth Howell        summary = False
4040e9727dbSSeth Howell    if args.memzone is not None:
4050e9727dbSSeth Howell        mem_info.print_memzone_summary(args.memzone)
4060e9727dbSSeth Howell        summary = False
4070e9727dbSSeth Howell
4080e9727dbSSeth Howell    if summary:
4090e9727dbSSeth Howell        mem_info.print_summary()
410