#!/usr/bin/env python3 # -*- coding:utf-8 -*- ############################################################################# # Copyright (c) 2023 Huawei Technologies Co.,Ltd. # # openGauss is licensed under Mulan PSL v2. # You can use this software according to the terms # and conditions of the Mulan PSL v2. # You may obtain a copy of Mulan PSL v2 at: # # http://license.coscl.org.cn/MulanPSL2 # # 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 v2 for more details. # ---------------------------------------------------------------------------- # Description : perf_probe.py setup a information set for configure ############################################################################# import math from base_utils.os.cpu_util import CpuArchitecture, CpuUtil from base_utils.os.disk_util import DiskUtil from impl.perf_config.basic.project import Project from impl.perf_config.basic.anti import AntiLog from impl.perf_config.basic.tuner import Tuner, TunerGroup, ShellTunePoint from impl.perf_config.probes.business import BsScenario ################################################ # BIOS # - BiosTuner ################################################ class BiosTuner(TunerGroup): def __init__(self): super(BiosTuner, self).__init__() def calculate(self): infos = Project.getGlobalPerfProbe() if infos.os.bios.support_smmu == 'Enable': sug = 'modify BIOS->Advances->MISC Config->Support Smmu to Disable.' Project.report.suggest(sug) Project.log('SUGGESTION: ' + sug) if infos.os.bios.cpu_prefetching == 'Enable': sug = 'modify BIOS->Advances->MISC Config->CPU Prefetching Configuration to Disable.' Project.report.suggest(sug) Project.log('SUGGESTION: ' + sug) if infos.os.bios.die_interleaving == 'Enable': sug = 'modify BIOS->Advances->MISC Config->Die Interleaving to Disable.' Project.report.suggest(sug) Project.log('SUGGESTION: ' + sug) ################################################ # CPU # - CPUTuner ################################################ class CPUTuner(TunerGroup): def __init__(self): super(CPUTuner, self).__init__() @staticmethod def calculate_numa_bind(): infos = Project.getGlobalPerfProbe() session_per_core = infos.business.parallel / infos.cpu.count() numa_bind = (infos.cpu.architecture() == CpuArchitecture.AARCH64 and infos.cpu.count() >= 32 and BsScenario.isOLTPScenario(infos.business.scenario) and session_per_core > 1) numa_bind_info = {'use': False, 'threadpool': [], 'network': '', 'walwriter': '', 'suggestions': []} if numa_bind: numa_bind_info['use'] = True ratio_for_net = 0.1 # cpu num for irq-bind / all cpu, 0.1 is ref tpcc 2P 4P. threadpool = [] network = [] for cpu_list in infos.cpu.numa(): cpu_count = len(cpu_list) count_for_net = max(math.floor(cpu_count * ratio_for_net), 1) threadpool += cpu_list[:cpu_count - count_for_net] network += cpu_list[cpu_count - count_for_net:] walwriter = [0] numactl_param = CpuUtil.cpuListToCpuRangeStr(threadpool) threadpool.remove(0) numa_bind_info['walwriter'] = CpuUtil.cpuListToCpuRangeStr(walwriter) numa_bind_info['threadpool'] = threadpool numa_bind_info['network'] = CpuUtil.cpuListToCpuRangeStr(network) suggestion = "If you use numactl for startup, you are advised to add param '-C {0}'{1}.".format( numactl_param, '' if infos.cpu.count() < 256 or len(infos.cpu.numa()) < 4 else "and '--preferred=0'." ) numa_bind_info['suggestions'].append(suggestion) return numa_bind_info def calculate(self): infos = Project.getGlobalPerfProbe() numa_bind_info = self.calculate_numa_bind() infos.cpu.notebook.write('numa_bind_info', numa_bind_info) def explain(self, apply=False): # tune threadpool in dbtuner and network in nerwork tuner pass ################################################ # MEMORY # - MemoryTuner # - MemHugePageTuner ############################################### class MemHugePageTuner(TunerGroup): def __init__(self): super(MemHugePageTuner, self).__init__() def calculate(self): infos = Project.getGlobalPerfProbe() if infos.memory.hugepage is None: return self._disable_huge_mem(infos) def _disable_huge_mem(self, infos): tune_enabled = (infos.memory.hugepage['enabled'] != 'never') if tune_enabled: cmd = "echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled" anti = "echo '{}' > /sys/kernel/mm/transparent_hugepage/enabled".format( infos.memory.hugepage['enabled']) desc = 'Tune hugepage enabled to never, old value is {}'.format(infos.memory.hugepage['enabled']) self.add(ShellTunePoint(cmd, anti, desc)) tune_defrag = (infos.memory.hugepage['defrag'] != 'never') if tune_defrag: cmd = "echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag" anti = "echo '{}' > /sys/kernel/mm/transparent_hugepage/defrag".format( infos.memory.hugepage['enabled']) desc = 'Tune hugepage defrag to never, old value is {}'.format(infos.memory.hugepage['enabled']) self.add(ShellTunePoint(cmd, anti, desc)) class MemoryTuner(TunerGroup): def __init__(self): super(MemoryTuner, self).__init__() self.hugepage = self.add(MemHugePageTuner()) ################################################ # DISK # - DiskTuner ############################################### class DiskTuner(TunerGroup): def __init__(self): super(DiskTuner, self).__init__() def calculate(self): infos = Project.getGlobalPerfProbe() gausshome_disk = DiskUtil.getMountPathByDataDir(infos.db.gauss_data) device = infos.disk.get(gausshome_disk) if device.fstype != 'xfs': sug = "Disk {0} is {1} format, you are advised to set the disk format to xfs ".format( device.device, device.fstype ) Project.report.suggest(sug) Project.log('SUGGESTION: ' + sug) ################################################ # DISK # - NetworkTuner # - NetworkIRQTuner # - EthtoolTuner # - NetConfigTuner ############################################### class NetworkIRQTuner(TunerGroup): def __init__(self): super(NetworkIRQTuner, self).__init__() self.script = Project.environ.get_builtin_script('irq_operate.sh') def calculate(self): infos = Project.getGlobalPerfProbe() numa_bind_info = infos.cpu.notebook.read('numa_bind_info') if numa_bind_info is None or not numa_bind_info.get('use'): return for ip in infos.db.ip: if ip == '*': continue gate = infos.network.get_gate(ip) if gate is None or gate.is_localhost() or gate.is_virbr() or gate.irq_binds is None: continue bind_list = CpuUtil.cpuRangeStrToCpuList(numa_bind_info.get('network')) roll_list = gate.irq_binds cmd = 'sh {0} bind {1} "{2}"'.format(self.script, gate.name, ' '.join([str(cpuid) for cpuid in bind_list])) anti = 'sh {0} bind {1} "{2}"'.format(self.script, gate.name, ' '.join([str(cpuid) for cpuid in roll_list])) desc = 'bind irq' self.add(ShellTunePoint(cmd, anti, desc)) class OffloadingTuner(TunerGroup): def __init__(self): super(OffloadingTuner, self).__init__() def calculate(self): infos = Project.getGlobalPerfProbe() for ip in infos.db.ip: if ip == '*': continue gate = infos.network.get_gate(ip) if gate is None or gate.is_localhost() or gate.is_virbr(): continue tune_tso = (gate.tso == 'off') if tune_tso: cmd = 'ethtool -K {} tso on'.format(gate.name) anti = 'ethtool -K {} tso off'.format(gate.name) desc = 'open offloading tso' self.add(ShellTunePoint(cmd, anti, desc)) tune_lro = (gate.lro == 'off') if tune_lro: cmd = 'ethtool -K {} lro on'.format(gate.name) anti = 'ethtool -K {} lro off'.format(gate.name) desc = 'open offloading lro' self.add(ShellTunePoint(cmd, anti, desc)) class NetConfigTuner(TunerGroup): def __init__(self): super(NetConfigTuner, self).__init__() def calculate(self): pass class NetworkTuner(TunerGroup): def __init__(self): super(NetworkTuner, self).__init__() self.network_irq = self.add(NetworkIRQTuner()) self.offloading = self.add(OffloadingTuner()) self.net_config = self.add(NetConfigTuner()) ################################################ # OS CONFIGURE AND SERVICE # - OSServiceTuner ################################################ class OSServiceTuner(TunerGroup): def __init__(self): super(OSServiceTuner, self).__init__() def calculate(self): infos = Project.getGlobalPerfProbe() if infos.os.service.sysmonitor is not None and infos.os.service.sysmonitor: cmd = "service sysmonitor stop" anti = "service sysmonitor start" desc = "stop sysmonitor" self.add(ShellTunePoint(cmd, anti, desc)) if infos.os.service.irqbalance is not None and infos.os.service.irqbalance: cmd = "service irqbalance stop" anti = "service irqbalance start" desc = "stop irqbalance" self.add(ShellTunePoint(cmd, anti, desc)) ################################################ # OS TUNER # - OSTuner # - BiosTuner # - CPUTuner # - MemoryTuner # - DiskTuner # - NetworkTuner # - OSServiceTuner ############################################### class OSTuner(TunerGroup): def __init__(self): super(OSTuner, self).__init__() self.bios = self.add(BiosTuner()) self.cpu = self.add(CPUTuner()) self.memory = self.add(MemoryTuner()) self.disk = self.add(DiskTuner()) self.network = self.add(NetworkTuner()) self.service = self.add(OSServiceTuner())