clickhouse与火焰图

简介: clickhouse与火焰图

最近再对clickhouse hive engine进行一些调优工作。本文将总结调优过程中常用的一些工具和命令。


火焰图


火焰图 (Flame Graph) 是性能优化大师 Bredan Gregg 创建的一种性能分析图标,因为它的样子近似火焰而得名。使用火焰图能够非常快速的定位到代码中的瓶颈,它就像一个在代码之海中航行的程序员的地图,指引着性能优化的方向。下图是clickhouse的一张火焰图。


image.png


火焰图的上下表示调用关系,下层的函数调用上层的函数。每个函数对应一个等高的长条,这个长条对应着该函数的某项指标,如cpu time/real time/memory allocate.

根据不同的指标,火焰图可以分为:


  • cpu火焰图。显示代码中函数的cpu耗时,函数宽度与cpu time成正比。主要用于分析进程中的cpu瓶颈


  • real火焰图。显示代码中函数的duration耗时,函数宽度与real time成正比。与cpu火焰图结合可用于分析进程中的io瓶颈


  • mem火焰图。显示代码中函数中申请内存的大小,函数宽度与memory allocation成正比。主要用于优化进程的内存占用。


对于clickhouse来说,性能瓶颈主要在于cpu和io。因此本文着重介绍如何生成cpu和real火焰图



clickhouse-flamegraph


clickhouse-flamegraph(https://github.com/Slach/clickhouse-flamegraph)是一个命令行工具,他能够将clickhouse系统表system.trace_log中的性能指标以query_id为粒度可视化,形成对应的火焰图。


在使用clickhouse-flamegraph之前,需要


  • 安装:参考官方文档,此处略


  • 配置:修改clickhouse配置文件:config.xml和users.xml,参考官方文档。这样做的目的是让clickhouse在query执行过程中,对cpu time, real time, memory allocate等指标进行采样。


安装和配置完成后,如何使用clickhouse-flame-graph生成火焰图呢?


  • 首先执行对应的query,


  • 然后记录对应的query_id


  • 运行clickhouse-flamegraph
$ clickhouse-flamegraph --dsn="http://localhost:8123/?user=default&password=xxx" --query-id=<query_id>
{"level":"info","dsn":"http://localhost:8123/?user=default&password=xxx","time":"2022-06-10T10:28:44+08:00","message":"connected to ClickHouse"}
{"level":"info","sqlFiles":1,"time":"2022-06-10T10:28:44+08:00","message":"write .sql files"}
{"level":"info","processedFiles":2,"time":"2022-06-10T10:28:44+08:00","message":"done processing"}


  • 最后查看火焰图。在当前目录下执行,可以看到以下几个文件
$ tree clickhouse-flamegraphs 
clickhouse-flamegraphs
└── f
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.CPU.svg
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.CPU.txt
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.MemorySample.svg
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.MemorySample.txt
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.Memory.svg
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.Memory.txt
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.Real.svg
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.Real.txt
    ├── 2694aa7a-f421-4727-a789-383a7bce05be.sql

其中,*.Memory.svg对应着mem火焰图,*.CPU.svg对应着cpu火焰图,*.Real.svg对应着real火焰图。*.sql中是本次查询的query语句。


我们看到,使用clickhouse-flamegraph生成火焰图还是很方便的。但是由于clickhouse的cpu time/real time的采样原理是在每个线程中一方面通过定时器每隔一定时间发出SIGUSR1和SIGUSR2 signal,另一方面注册信号处理函数,在收到signal的同时,将当前stack trace记录到system.trace_log中去。


由于clickhouse自带cpu time/real time的实现原理,clickhouse-flamegraph有两个缺点

  • cpu time和real time的采样时间间隔太长。以笔者调试hive engine查询的经验,目前20ms是比较可靠的间隔,间隔再短点就无法保证query正常执行。


  • 开启cpu time和real time采样会明显拖慢query运行速度,导致火焰图失真。




perf


perf是内置于linux kernel中的profiling工具,它能监测各种硬件和软件事件,被广泛用于性能瓶颈的查找和热点代码的定位。正因为他是内置的profiling工具,perf能够避免clickhouse-flamegraph的的上述缺点。perf的缺省采样频率是4000/s, 使用perf也不会导致被观测进程产生明显的性能衰减。


那么如何使用perf生成cpu和real火焰图呢?


  • 首先在clickhouse加上以下编译参数,避免debug信息丢失导致火焰图不准确。

clickhouse在使用-O2编译的时候,会默认带上-fomit-frame-pointer和-fptimize-sibling-calls参数。这些参数通过编译阶段的优化,对运行是的性能有所提升,但是会让debug信息变得不完整。



**-fomit-frame-pointer**

Don't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an extra register available in many functions. It also makes debugging impossible on some machines.

-foptimize-sibling-calls

This option determines whether the compiler optimizes tail recursive calls. It enables conversion of tail recursion into loops.

If you do not want to optimize tail recursive calls, specify -fno-optimize-sibling-calls.

Tail recursion is a special form of recursion that doesn't use stack space. In tail recursion, a recursive call is converted to a GOTO statement that returns to the beginning of the function. In this case, the return value of the recursive call is only used to be returned. It is not used in another expression. The recursive function is converted into a loop, which prevents modification of the stack space used.


if (COMPILER_CLANG)
    # generate ranges for fast "addr2line" search
    if (NOT CMAKE_BUILD_TYPE_UC STREQUAL "RELEASE")
        set(COMPILER_FLAGS "${COMPILER_FLAGS} -gdwarf-aranges")
    endif ()
    if (HAS_USE_CTOR_HOMING)
        # For more info see https://blog.llvm.org/posts/2021-04-05-constructor-homing-for-debug-info/
        if (CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO")
            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -fuse-ctor-homing")
            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Xclang -fuse-ctor-homing")
        endif()
    endif()
  # 添加以下两行
  # 
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls")
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fno-optimize-sibling-calls")
endif ()


  • 通过clickhouse-benchmark运行要profile的query。如

./clickhouse benchmark -i 5 --query "select day, hour, appid, count(1) from test.csc_like_all_push_hour_text where day = '2022-02-03' and hour = '00' group by day, hour, appid"

  • 在运行query的同时,执行perf record, 分别对cyclescpu-clock进行采集。其中cycles事件对应cpu time, cpu-clock事件对应real time. 如
perf record -ag -p <clickhouse-pid>  -e  cycles  -- sleep  15
perf record -ag -p <clickhouse-pid>  -e  cpu-clock  -- sleep  15
perf script > out.perf && stackcollapse-perf.pl out.perf > out.folded && flamegraph.pl out.folded > out.svg

perf生成的cpu火焰图的示例:

image.png


perf生成的real火焰图的示例:

image.png



总结


本文介绍了两种为clickhouse进程生成火焰图的方法:clickhouse-flamegraph与perf。clickhouse-flamegraph的优点是操作简单,缺点是被观测进程有性能衰减、采样间隔太长。


perf在使用上更通用且更精确,但是操作也更复杂。因此建议将clickhouse-flamegraph用于定性分析,快速判定哪个模块是瓶颈;将perf用于定量分析,定位哪个具体函数是瓶颈,并衡量性能优化后的收益。



相关文章
|
Linux
如何看懂火焰图
如何看懂火焰图
1141 0
如何看懂火焰图
|
1月前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
【11月更文挑战第6天】在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
|
4月前
|
关系型数据库 分布式数据库 数据库
基于PolarDB的图分析:通过表格将数据快速导入到图
本文介绍了使用 PolarDB PostgreSQL兼容版的AGE插件时,在大数据量下,快速导入数据的方法。可以快速将图数据库中亿级以上的节点和边快速导入到数据库中,避免了插入边时进行查询带来的性能瓶颈。
|
7月前
|
JavaScript
性能工具之 FlameGraph 火焰图
其实很多类似 perf 的工具都能生成火焰图,像 systemtap/dtrace 之类的 并且这个思路,现在在 js 优化、代码优化等各方面都有具体的应用了 至于怎么理解? 简单点说,就是看谁又平又宽
160 7
性能工具之 FlameGraph 火焰图
|
Ubuntu
代码性能展现 火焰图
代码性能展现 火焰图
74 0
|
Go
pprof新增的火焰图实现
pprof新增的火焰图实现
90 0
|
Ubuntu
perf + 火焰图分析软件性能
perf + 火焰图分析软件性能
186 0
|
监控 数据可视化 前端开发
火焰图是怎么画出来的?Pyroscope源码解析之火焰图
火焰图简述火焰图(Flame Graph) 由Brendan Gregg在2011年创造,是一种可视化程序性能分析工具,它可以帮助开发人员追踪程序的函数调用以及调用所占用的时间,并且展示出这些信息。一般性解释火焰图的基本思想是将程序的函数调用栈转化为一个矩形的 “火焰” 形图像,每个矩形的宽度表示该函数所占用的比例,高度表示函数的调用深度(也就是递归调用的层数)。通过比较不同时间点的火焰图,可以快
627 0
|
前端开发 数据可视化 关系型数据库
巧用 “ 火焰图 ” 快速分析链路性能
巧用 “ 火焰图 ” 快速分析链路性能
352 0
巧用 “ 火焰图 ” 快速分析链路性能
|
Arthas 测试技术 网络安全
Profiler 生成火焰图 | 学习笔记
快速学习 Profiler 生成火焰图
Profiler 生成火焰图 | 学习笔记