8.2.4  openGauss关键源码解析

X-Tuner在项目中的源代码路径为:openGauss-server/src/gausskernel/dbmind/tools/xtuner。

1. 项目结构

X-Tuner文件结构如表8-2所示。

表8-2  X-Tuner主要文件结构

文件结构

说明

setup.py

安装脚本

share

配置文件示例

test

单元测试文件的目录

tuner

调优程序主代码目录

tuner/algorithms

算法子模块

tuner/algorithms/pso.py

粒子群算法

tuner/benchmark

压力测试驱动脚本存储的目录

tuner/benchmark/sysbench.py

sysbench驱动脚本

tuner/benchmark/template.py

压力测试驱动脚本的模板

tuner/benchmark/tpcc.py

TPC-C驱动脚本

tuner/benchmark/tpcds.py

TPC-DS驱动脚本

tuner/benchmark/tpch.py

TPC-H驱动脚本

tuner/character.py

获取系统workload特征的模块

tuner/db_agent.py

封装数据库操作的模块

tuner/db_env.py

离线调优流程控制模块

tuner/env.py

保持与强化学习gym库的接口一致

tuner/exceptions.py

定义常见异常

tuner/executor.py

封装shell连接

knobs/knob.py

定义参数相关类

knobs/main.py

入口文件

knobs/recommend.py

定义参数推荐的算法与规则

knobs/recorder.py

记录调优过程的模块

knobs/utils.py

定义一些工具函数

knobs/xtuner.conf

默认配置文件

knobs/xtuner.py

调优主流程控制模块

knobs/README.md

安装脚本

2. 总体流程解析

入口总体流程在main.py中给出,main函数的核心代码如下:

def main():

   …

# 通过命令行参数或连接信息文件构建db_info字典,利用该字典中的信息可以登录到数据库实例和宿主机上

    db_info = build_db_info(args)

    if not db_info:

        parser.print_usage()

        return -1



    # 解析配置文件中给定的配置项

    config = get_config(args.tuner_config_file)

    if not config:

        return -1



try:

    # 当获取到足够的信息后,进入工具的执行流程

        return procedure_main(mode, db_info, config)

    except Exception as e:

        logging.exception(e)

        print('FATAL: An exception occurs during program running. '

              'The exception information is "%s". '

              'For details about the error cause, please see %s.' % (e, config['logfile']),

              file=sys.stderr, flush=True)

        return -1

可以看到main函数主要是做一些参数、命令行的校验、收集工作,核心流程定义在xtuner.py的procedure_main函数中,该函数的核心代码如下:

def procedure_main(mode, db_info, config):

    # 权限最小化

    os.umask(0o0077)

    # 初始化日志模块

    set_logger(config['logfile'])

logging.info('Starting... (mode: %s)', mode)

# 利用new_db_agent函数构造DB_Agent对象,该对象是唯一对数据库操作进行封装的对象

    db_agent = new_db_agent(db_info)



    # 如果用户没有通过配置文件指定负载类型,则通过预定义的算法或规则进行自动判断

    if config['scenario'] in WORKLOAD_TYPE.TYPES:

        db_agent.metric.set_scenario(config['scenario'])

    else:

        config['scenario'] = db_agent.metric.workload_type

    # 同上,如果用户设置为自动模式,则使用下述默认规则补充

    if config['tune_strategy'] == 'auto':

        # If more iterations are allowed, reinforcement learning is preferred.

        if config['rl_steps'] * config['max_episode_steps'] > 1500:

            config['tune_strategy'] = 'rl'

        else:

            config['tune_strategy'] = 'gop'



logging.info("Configurations: %s.", config)

# 如果在配置文件中指定了tuning_list配置项,并且非reocmmend模式,则加载该待调优参数列表的配置文件,否则通过recommend_knobs函数智能获取待调优参数列表

 if config['tuning_list'].strip() != '' and mode != 'recommend':

        knobs = load_knobs_from_json_file(config['tuning_list'])

    else:

        print("Start to recommend knobs. Just a moment, please.")

        knobs = recommend_knobs(mode, db_agent.metric)

    if not knobs:

        logging.fatal('No recommended best_knobs for the database. Stop the execution.')

        return -1

   

    # 如果是调优和训练模式,由于某些数据库参数是需要重启后才生效的,因此可能会伴随着反复的重启过程

    if mode != 'recommend':  # 不为recommend模式,就只能是tune或者train模式,而这两种模式都是离线过程,需要反复迭代

  prompt_restart_risks()  # 告知用户调优过程中有数据库重启的风险

        # 初始化调优中的记录类

        recorder = Recorder(config['recorder_file'])

      

        # 分别读取配置文件中的三个配置项:benchmark_scriptbenchmark_path以及benchmark_cmd,通过这三个配置项就可以获取到benchmark驱动脚本的实例,可以用它来衡量数据库的性能

bm = benchmark.get_benchmark_instance(config['benchmark_script'],

                                              config['benchmark_path'],

                                              config['benchmark_cmd'],

                                              db_info)

        

        # 初始化数据库调优环境实例,该对象封装了迭代过程,保持与强化学习库gym.Env的接口一致

env = DB_Env(db_agent, benchmark=bm, recorder=recorder,

                     drop_cache=config['drop_cache'],

                     mem_penalty=config['used_mem_penalty_term'])

        env.set_tuning_knobs(knobs)

        # 识别不同的模式,不同模式执行对应的子程序

        if mode == 'train':

            rl_model('train', env, config)

        elif mode == 'tune':

            …

    # 执行到此处时,已经完成调优过程。下述代码负责将调优结果输出

    knobs.output_formatted_knobs()

    if config['output_tuning_result'] != '':

        with open(config['output_tuning_result'], 'w+') as fp:

        

            # train模式是强化学习独有的模式,在该模式下,只输出调优参数,不输出报告参数(建议参数)。这是因为,在强化学习的tune模式下,待调优参数列表应当与train模式下保存的调优列表需要完全相同,即调优参数名相同、调优范围相同、各个参数的顺序相同,否则会导致输入特征不符合。

     knobs.dump(fp, dump_report_knobs=mode != 'train')

    logging.info('X-Tuner is executed and ready to exit. '

                 'Please refer to the log for details of the execution process.')

    return 0

       

综上,调优程序是一个独立于数据库内核之外的工具,需要提供数据库及其所在实例的用户名和登录密码信息,以便控制数据库执行benchmark进行性能测试;在启动调优程序前,要求用户测试环境交互正常,能够正常跑通benchmark测试脚本、能够正常连接数据库。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐