追本溯源丨MogDB代码解析之关于CPU占用问题的优化

2022-01-12 00:00:00 数据 代码 计算 云和 采用

openGauss自去年“6·30”开源以来,受到了业界的普遍关注,其以性能、企业级内核和高度的安全增强,为数据库开源社区注入了新的活力。云和恩墨作为openGauss的重要合作伙伴,积极参与到开源生态建设中来,时间推出了基于openGauss的企业版 – MogDB,并以此为基础,围绕高可用、安全、自动化运维、数据库一体机、SQL审核优化等企业需求推出整体解决方案。

本期开始,小编将连载《追本溯源丨MogDB代码解析》系列文章,以期为读者更好、更深入地学习openGauss提供帮助。

1.

问题描述

空闲时的openGauss也会占用一定的CPU,通过perf top,htop等工具定位到是Percentile线程占用。


02.

代码解读

  • 代码位置:

    https://gitee.com/opengauss/openGauss-server/blob/master/src/gausskernel/cbb/instruments/percentile/percentile.cpp (复制链接至浏览器中打开或直接点击文末“阅读原文”)

  • Percentile线程的功能作用,以及其内部实现如下。


01

PercentileMain

PercentileMain初始化于系统启动(postmaster.cpp)时候,无论是否启用统计特性,线程都会初始化并启动。

主循环流程:

  • 根据信号响应重载配置文件。主要相关参数:

    • 是否启用统计信息

    • 统计信息计算频率(默认10s)

  • 启动SubPercentileMain执行实际的采集计算。

  • sleep 10s
    采用CpuCyclesLevelTime(mot相关方法,根据cpu循环时间计算得到的时间,应该是为了arm架构的优化做的方法,这里x86机器采用rdtsc指令,arm采用cntvct_el0指令)。



02

SubPercentileMain

主循环:
  • while跳出条件判断is_enable_percentile_thread,这里默认情况下,只要是单节点模式,必然为true,只有分布式模式下的数据节点才会是false。

  • 根据信号响应重载配置文件。

  • 执行calculatePercentileOfSingleNode计算统计信息(分布式下采用calculatePercentileOfMultiNode计算)。

  • 执行pg_usleep 这里怀疑是笔误,入参仅10,也就是10微秒(delay.tv_usec = microsec % 1000000L;此处采用系统select调用作为sleep机制,并非系统api sleep或者nanosleep)。



03

calculatePercentileOfSingleNode

主流程:

  • 如果enable_instr_rt_percentile参数设置为false,这里跳出返回,不执行下面的逻辑。

  • pgstat_fetch_sql_rt_info_counter获取所有sql数量。

  • pgstat_fetch_sql_rt_info_internal获取所有sql的响应时间。

  • PercentileSpace::heapSort进行响应时间排序。

  • PercentileSpace::CalculatePercentile 计算响应时间比例。



04

已知问题

SubPercentileMain中,while循环中,pg_usleep(10)导致非常高频的系统select调用。

测试代码:

#include <sys/select.h>

#include <time.h>

int main( int argc,char

{    

   long microsec=10;

   for (int i=;i<1000000000;i++){

       struct timeval delay;

       delay.tv_sec = microsec / 1000000L;
       delay.tv_usec = microsec % 1000000L;
       (void)select(, NULL, NULL, NULL, &delay);

}

   return ;

}
03.

解决办法

  • 设置enable_instr_rt_percentile在is_enable_percentile_thread中进行判断,而非calculatePercentileOfSingleNode。

  • 修改pg_usleep调用到1毫秒或者10毫秒。

将第222行的 sleep(SLEEP_INTERVAL); 修改为 sleep(SLEEP_INTERVAL*1000);

第271行添加如下代码:

if (!u_sess->attr.attr_common.enable_instr_rt_percentile){

   return false;

}

重新编译安装并设置参数:
enable_instr_rt_percentile=off


04.

效果对比

我们已经将上述修改优化到了MogDB里,下面可以就社区版(openGauss)和商业发行版(MogDB)做个对比:

1. 分别启动MogDB和openGauss两个容器

[root@ecs-x86-001 ~]# docker run --name opengauss --privileged=true -d -e GS_PASSWORD=Enmo@123  opengauss:1.1.0
8f74e5f4d07fbec0d58dfaea75ef3816a821b6383be04c1776d8a057abd9e12c
[root@ecs-x86-001 ~]# docker run --name mogdb --privileged=true -d -e GS_PASSWORD=Enmo@123  mogdb:1.1.0
70c4ef716c33a3436a5fe7188b7f30dcf60467276b40acac997fec7ca8bee4af

2. 查看进程和copyright

[root@ecs-x86-001 ~]# docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED              STATUS              PORTS      NAMES
70c4ef716c33   mogdb:1.1.0       "entrypoint.sh mogdb"    About a minute ago   Up About a minute   5432/tcp   mogdb
8f74e5f4d07f   opengauss:1.1.0   "entrypoint.sh gauss…"   About a minute ago   Up About a minute   5432/tcp   opengauss
[root@ecs-x86-001 ~]# docker top mogdb
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
70                  4060                4041                0                   17:22               ?                   00:00:00            mogdb
[root@ecs-x86-001 ~]# docker top opengauss
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
70                  3644                3623                6                   17:21               ?                   00:00:08            gaussdb
[root@ecs-x86-001 ~]# docker exec -it opengauss bash
[root@8f74e5f4d07f /]# su - omm -c 'gsql -d postgres -p5432 -r -c"\copyright"'
GaussDB Kernel Database Management System
Copyright (c) Huawei Technologies Co., Ltd. 2018. All rights reserved.

[root@ecs-x86-001 ~]# docker exec -it mogdb bash
[root@70c4ef716c33 /]# su - omm -c 'gsql -d postgres -p5432 -r -c"\copyright"'
MogDB Kernel Database Management System
Copyright (c) Yunhe Enmo (Beijing) Information Technology Co., Ltd. Copyright © 2009-2020 , All rights reserved.

3. top对比实际效果

可以看到终效果,openGauss社区版空转时CPU消耗接近10%,而MogDB将这一数值降到了0.3%。

[root@ecs-x86-001 ~]# top -p 4060,3644
[root@ecs-x86-001 ~]# top -p 4060,3644
top - 17:28:05 up 29 days,  2:01,  1 user,  load average: 0.05, 0.07, 0.06
Tasks:   2 total,   0 running,   2 sleeping,   0 stopped,   0 zombie%Cpu(s):  0.0 us,  0.2 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 stKiB Mem : 65806096 total, 57493216 free,  3526940 used,  4785940 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 60510156 avail Mem

 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
3644 70        20   0 1764380 615248 113760 S   8.6  0.9   0:29.56 gaussdb
4060 70        20   0 1740936 591484 110196 S   0.3  0.9   0:01.44 mogdb


MogDB是在高可靠、高性能的openGauss企业级内核基础上,通过在高可用、易维护、平缓迁移等方向提供的增强,为企业提供的国产数据库新选择。感兴趣的朋友可以下载容器镜像进行体验。

  • docker hub地址:

    https://hub.docker.com/repository/docker/enmotech/opengauss

  • github地址:

    https://github.com/enmotech/enmotech-docker-opengauss

  • gitee地址:

    https://gitee.com/opengauss/openGauss-server/tree/master/docker


数据驱动,成就未来,云和恩墨,不负所托!

云和恩墨,以“数据驱动 · 成就未来”为使命,专注于DT (数据技术)领域,致力于为全球的关键大型客户、高成长客户、中小客户和个人提供富有竞争力的解决方案、产品和服务,实现组织和个人的发展成功。
我们的核心业务:围绕数据资产,在数据产生、处理、应用和管理的端到端过程中,持续创新,研发云化、分布式、智能的DT产品和服务,包括DI(数据智能),DevOps(开发运维协同),dbPaaS(数据库云化管理),SDS(软件定义存储)和DMS(数据管理服务)等。
云和恩墨成立于2011年,截止到2020年底,600多名员工分布在国内外的32个营销服务网络,累计直接服务1,000多个组织,50,000多个业务系统,超过300,000个行业从业者。

相关文章