Zhipeng Xie 4335408875 atune: init code
upload code to gitee

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
2019-11-13 17:14:15 +08:00

237 lines
9.5 KiB
Python
Executable File

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Huawei Technologies Co., Ltd.
# A-Tune is licensed under the Mulan PSL v1.
# You can use this software according to the terms and conditions of the Mulan PSL v1.
# You may obtain a copy of Mulan PSL v1 at:
# http://license.coscl.org.cn/MulanPSL
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v1 for more details.
# Create: 2019-10-29
"""
The sub class of the monitor, used to collect memory bandwidth stat info.
"""
import sys
import logging
import subprocess
import getopt
import re
import json
if __name__ == "__main__":
sys.path.insert(0, "./../../")
from monitor.common import *
from monitor.memory import topo
logger = logging.getLogger(__name__)
class MemBandwidth(Monitor):
"""To collect memory bandwidth stat info"""
_module = "MEM"
_purpose = "BANDWIDTH"
_option = "-a -e {events} --interval-print {int} --interval-count 1"
__evs1620 = {
"c0d0c0_r": "hisi_sccl1_ddrc0/flux_rd/",
"c0d0c1_r": "hisi_sccl1_ddrc1/flux_rd/",
"c0d0c2_r": "hisi_sccl1_ddrc2/flux_rd/",
"c0d0c3_r": "hisi_sccl1_ddrc3/flux_rd/",
"c0d0c0_w": "hisi_sccl1_ddrc0/flux_wr/",
"c0d0c1_w": "hisi_sccl1_ddrc1/flux_wr/",
"c0d0c2_w": "hisi_sccl1_ddrc2/flux_wr/",
"c0d0c3_w": "hisi_sccl1_ddrc3/flux_wr/",
"c0d1c0_r": "hisi_sccl3_ddrc0/flux_rd/",
"c0d1c1_r": "hisi_sccl3_ddrc1/flux_rd/",
"c0d1c2_r": "hisi_sccl3_ddrc2/flux_rd/",
"c0d1c3_r": "hisi_sccl3_ddrc3/flux_rd/",
"c0d1c0_w": "hisi_sccl3_ddrc0/flux_wr/",
"c0d1c1_w": "hisi_sccl3_ddrc1/flux_wr/",
"c0d1c2_w": "hisi_sccl3_ddrc2/flux_wr/",
"c0d1c3_w": "hisi_sccl3_ddrc3/flux_wr/",
"c1d0c0_r": "hisi_sccl5_ddrc0/flux_rd/",
"c1d0c1_r": "hisi_sccl5_ddrc1/flux_rd/",
"c1d0c2_r": "hisi_sccl5_ddrc2/flux_rd/",
"c1d0c3_r": "hisi_sccl5_ddrc3/flux_rd/",
"c1d0c0_w": "hisi_sccl5_ddrc0/flux_wr/",
"c1d0c1_w": "hisi_sccl5_ddrc1/flux_wr/",
"c1d0c2_w": "hisi_sccl5_ddrc2/flux_wr/",
"c1d0c3_w": "hisi_sccl5_ddrc3/flux_wr/",
"c1d1c0_r": "hisi_sccl7_ddrc0/flux_rd/",
"c1d1c1_r": "hisi_sccl7_ddrc1/flux_rd/",
"c1d1c2_r": "hisi_sccl7_ddrc2/flux_rd/",
"c1d1c3_r": "hisi_sccl7_ddrc3/flux_rd/",
"c1d1c0_w": "hisi_sccl7_ddrc0/flux_wr/",
"c1d1c1_w": "hisi_sccl7_ddrc1/flux_wr/",
"c1d1c2_w": "hisi_sccl7_ddrc2/flux_wr/",
"c1d1c3_w": "hisi_sccl7_ddrc3/flux_wr/"}
__cnt1620 = {
"Total": 0,
"CPU0": 0,
"CPU1": 0,
"CPU0_Die0": 0,
"CPU0_Die1": 0,
"CPU1_Die0": 0,
"CPU1_Die1": 0,
"CPU0_Die0_R": 0,
"CPU0_Die1_R": 0,
"CPU1_Die0_R": 0,
"CPU1_Die1_R": 0,
"CPU0_Die0_W": 0,
"CPU0_Die1_W": 0,
"CPU1_Die0_W": 0,
"CPU1_Die1_W": 0,
"Total_Max": 0,
"CPU0_Max": 0,
"CPU1_Max": 0,
"Total_Util": 0}
def __init__(self, user=None):
Monitor.__init__(self, user)
self.__cmd = "perf stat"
self.__interval = 1000
self.__evs = self.__evs1620
self.__cnt = self.__cnt1620
self.__cnt["CPU0_Max"] = self.__get_theory_bandwidth(0) / 1024 / 1024
self.__cnt["CPU1_Max"] = self.__get_theory_bandwidth(1) / 1024 / 1024
self.__events = ""
for e in self.__evs:
self.__events = self.__events + self.__evs[e] + ","
self.__events = self.__events.strip(",")
help_info = "--fields="
for c in self.__cnt:
help_info = help_info + c + "/"
help_info = help_info.strip("/")
self.decode.__func__.__doc__ = Monitor.decode.__doc__ % (help_info)
def _get(self, para=None):
if para is not None:
opts, args = getopt.getopt(para.split(), None, ['interval='])
for opt, val in opts:
if opt in ('--interval'):
if val.isdigit():
self.__interval = int(val) * 1000
else:
err = ValueError(
"Invalid parameter: {opt}={val}".format(
opt=opt, val=val))
logger.error(
"{}.{}: {}".format(
self.__class__.__name__,
sys._getframe().f_code.co_name,
str(err)))
raise err
continue
output = subprocess.check_output(
"{cmd} {opt}".format(
cmd=self.__cmd,
opt=self._option.format(
int=self.__interval,
events=self.__events)).split(),
stderr=subprocess.STDOUT)
return output.decode()
def __get_theory_bandwidth(self, socket):
memtopo = topo.MemTopo()
info_json = memtopo.report("json", None)
info = json.loads(info_json)
width = 0
dimms = [[0 for i in range(8)] for i in range(8)]
for dimm in info["memorys"][0]["children"]:
if dimm.get("size") is None:
continue
locator = memtopo._table_get_locator(dimm["slot"])
if dimms[locator[0]][locator[1]] == 0:
dimms[locator[0]][locator[1]] = dimm["width"] * \
memtopo._table_get_freq(dimm["description"]) / 8
ret = 0
for channel in dimms[socket]:
ret += channel
return ret
def __read_counters(self, c_evs):
self.__cnt["CPU0_Die0_R"] = ((int(c_evs["c0d0c0_r"]) + int(c_evs["c0d0c1_r"]) + int(
c_evs["c0d0c2_r"]) + int(c_evs["c0d0c3_r"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU0_Die1_R"] = ((int(c_evs["c0d1c0_r"]) + int(c_evs["c0d1c1_r"]) + int(
c_evs["c0d1c2_r"]) + int(c_evs["c0d1c3_r"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU1_Die0_R"] = ((int(c_evs["c1d0c0_r"]) + int(c_evs["c1d0c1_r"]) + int(
c_evs["c1d0c2_r"]) + int(c_evs["c1d0c3_r"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU1_Die1_R"] = ((int(c_evs["c1d1c0_r"]) + int(c_evs["c1d1c1_r"]) + int(
c_evs["c1d1c2_r"]) + int(c_evs["c1d1c3_r"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU0_Die0_W"] = ((int(c_evs["c0d0c0_w"]) + int(c_evs["c0d0c1_w"]) + int(
c_evs["c0d0c2_w"]) + int(c_evs["c0d0c3_w"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU0_Die1_W"] = ((int(c_evs["c0d1c0_w"]) + int(c_evs["c0d1c1_w"]) + int(
c_evs["c0d1c2_w"]) + int(c_evs["c0d1c3_w"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU1_Die0_W"] = ((int(c_evs["c1d0c0_w"]) + int(c_evs["c1d0c1_w"]) + int(
c_evs["c1d0c2_w"]) + int(c_evs["c1d0c3_w"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU1_Die1_W"] = ((int(c_evs["c1d1c0_w"]) + int(c_evs["c1d1c1_w"]) + int(
c_evs["c1d1c2_w"]) + int(c_evs["c1d1c3_w"])) * 32 / 1024 / 1024) * 1000 / self.__interval
self.__cnt["CPU0_Die0"] = self.__cnt["CPU0_Die0_R"] + \
self.__cnt["CPU0_Die0_W"]
self.__cnt["CPU0_Die1"] = self.__cnt["CPU0_Die1_R"] + \
self.__cnt["CPU0_Die1_W"]
self.__cnt["CPU1_Die0"] = self.__cnt["CPU1_Die0_R"] + \
self.__cnt["CPU1_Die0_W"]
self.__cnt["CPU1_Die1"] = self.__cnt["CPU1_Die1_R"] + \
self.__cnt["CPU1_Die1_W"]
self.__cnt["CPU0"] = self.__cnt["CPU0_Die0_R"] + self.__cnt["CPU0_Die0_W"] + \
self.__cnt["CPU0_Die1_R"] + self.__cnt["CPU0_Die1_W"]
self.__cnt["CPU1"] = self.__cnt["CPU1_Die0_R"] + self.__cnt["CPU1_Die0_W"] + \
self.__cnt["CPU1_Die1_R"] + self.__cnt["CPU1_Die1_W"]
self.__cnt["Total"] = self.__cnt["CPU0"] + self.__cnt["CPU1"]
self.__cnt["Total_Max"] = self.__cnt["CPU0_Max"] + self.__cnt["CPU1_Max"]
self.__cnt["Total_Util"] = self.__cnt["Total"] / self.__cnt["Total_Max"] * 100
def decode(self, info, para):
if para is None:
return info
c_evs = self.__evs.copy()
for e in self.__evs:
pattern = "^\ {2,}(\d.*?)\ {2,}(\d.*?)\ {2,}(" + \
self.__evs[e] + ").*?"
searchObj = re.search(pattern, info, re.ASCII | re.MULTILINE)
if searchObj is not None:
c_evs[e] = searchObj.group(2).replace(",", "")
else:
err = LookupError("Fail to find {}".format(self.__evs[e]))
logger.error(
"{}.{}: {}".format(
self.__class__.__name__,
sys._getframe().f_code.co_name,
str(err)))
raise err
self.__read_counters(c_evs)
fields = []
ret = ""
opts, args = getopt.getopt(para.split(), None, ['fields='])
for opt, val in opts:
if opt in ('--fields'):
fields.append(val)
continue
for f in fields:
ret = ret + " {:.2f}".format(self.__cnt[f])
return ret
if __name__ == "__main__":
if len(sys.argv) != 3:
print('usage: ' + sys.argv[0] + ' fmt path')
sys.exit(-1)
ct = MemBandwidth("UT")
# help(ct)
ct.report(sys.argv[1], sys.argv[2], "--interval=5;--fields=Total --fields=CPU0 --fields=CPU1 --fields=Total_Max --fields=CPU0_Max --fields=CPU1_Max --fields=Total_Util")