《Linux性能优化实战》学习笔记 Day01

news2024/11/26 1:46:35

学习目标

系统优化的旅程上,对操作系统相关的优化是绕不开的,主动出击,将零星的知识体系化。今后遇到问题,能够加入自己的体系树中,即使专栏中没有提到,自己也能够想办法深入。

希望在这次课程后,我能够在操作系统调参,性能短板分析等问题上有足够的收获。

谨记老师说的,不积压不懂的地方。

之后也要学习《性能之巅》这一本老师推荐的书。

专栏示例代码:https://github.com/russelltao/geektime_distrib_perf

开篇词 | 万变不离其宗,性能优化也有章可循

原文摘抄

性能优化最根本的目的,还是要跟上业务的发展脚步。

性能就是最好的面试题,它从算法到架构,既能考察候选人的潜力,也能考察候选人的工程能力。

系统化的性能学习路径:
在这里插入图片描述

通过这份脑图,你会发现,我是从 4 个方面来梳理的,这其实就是我们在提升一个新系统的性能时,可以入手的 4 个层次。

首先,你可以从提升单机进程的性能入手,包括高效地使用主机的 CPU、内存、磁盘等硬件,通过并发编程提升吞吐量,根据业务特性选择合适的算法。

其次,分布式系统是由各个组件通过网络连接在一起,所以优化传输层网络可以让所有组件同时受益。具体优化时,你可以从降低请求的时延,提升总体吞吐量两个方向入手。

再次呢,你要对业务消息采用更高效的编码方式,这既包括协议头、包体的优化,也包括 TLS 安全层的性能提升。具体优化时,既要深入静态编码,也要从动态的增量编码上优化。同时,调整消息的交互方式也能提升性能。

最后,我们再从集群整体上进行架构层面的优化。基于 ACP、AKF、NWR 等分布式理论,我们的优化方向仍然是降低时延和提升吞吐量,但实现方式则要运用分而治之的思想,调度集群中的所有结点协作配合,完成性能优化目标。

心得体会

  1. 性能优化真的是一个很宽,又很深的一项能力。理论和实践结合才能到达巅峰。

工作体验

  1. 工作中,对应用用到的常用组件都做了很多优化。但是着实遇到一些问题,例如终端用户的延迟实在高,如何排查并协调网络部门来定位缩短耗时。对于kyligence这样一个商业化不开源的查询引擎,又如何分析其性能,定位系统能够调参的位置呢?

01 | CPU缓存:怎样写代码能够让CPU执行得更快?

原文摘抄

  1. 很多同学并不清楚 CPU 缓存的运行规则,不知道如何写代码才能够配合 CPU 缓存的工作方式,这样,便放弃了可以大幅提升核心计算代码执行速度的机会。

  2. CPU 缓存通常分为大小不等的三级缓存。CPU 缓存的材质 SRAM 比内存使用的 DRAM 贵许多。可以通过如下命令查询CPU缓存大小:

dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index0/size 
32K
dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index1/size 
32K
dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index2/size 
256K
dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index3/size 
12288K
dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index4/size 
cat: /sys/devices/system/cpu/cpu0/cache/index4/size: 没有那个文件或目录

每个核心都有自己的一、二级缓存,但三级缓存却是一颗 CPU 上所有核心共享的。
在这里插入图片描述

缓存要比内存快很多。CPU 访问一次内存通常需要 100 个时钟周期以上,而访问一级缓存只需要 4~5 个时钟周期,二级缓存大约 12 个时钟周期,三级缓存大约 30 个时钟周期(对于 2GHZ 主频的 CPU 来说,一个时钟周期是 0.5 纳秒。因此,我们的代码优化目标是提升 CPU 缓存的命中率。

  1. 在查看 CPU 缓存时会发现有 2 个一级缓存(比如 Linux 上就是上图中的 index0 和 index1),这是因为,CPU 会区别对待指令与数据。比如,“1+1=2”这个运算,“+”就是指令,会放在一级指令缓存中,而“1”这个输入数字,则放在一级数据缓存中。虽然在冯诺依曼计算机体系结构中,代码指令与数据是放在一起的,但执行时却是分开进入指令缓存与数据缓存的,因此我们要分开来看二者的缓存命中率

  2. 不同代码性能

// array[j][i]和 array[i][j]访问数组元素,哪一种性能更快?
       for(i = 0; i < N; i+=1) {
           for(j = 0; j < N; j+=1) {
               array[i][j] = 0;
           }
       }

二维数组 array 所占用的内存是连续的,缓存已经把紧随其后的 3 个元素也载入了,CPU 通过快速的缓存来读取后续 3 个元素就可以。

到这里我们还有 2 个问题没有搞明白:为什么两者的执行时间有约 7、8 倍的差距呢?载入 array[0][0]元素时,缓存一次性会载入多少元素呢?

其实这两个问题的答案都与 CPU Cache Line 相关:

dark@dark:~$ cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size 
64

由于 64 位操作系统的地址占用 8 个字节(32 位操作系统是 4 个字节),因此,每批 Cache Line 最多也就能载入不到 8 个二维数组元素,所以性能差距大约接近 8 倍。

因此,遇到这种遍历访问数组的情况时,按照内存布局顺序访问将会带来很大的性能提升。

关于 CPU Cache Line 的应用其实非常广泛,如果你用过 Nginx,会发现它是用哈希表来存放域名、HTTP 头部等数据的,这样访问速度非常快,而哈希表里桶的大小如 server_names_hash_bucket_size,它默认就等于 CPU Cache Line 的值。由于所存放的字符串长度不能大于桶的大小,所以当需要存放更长的字符串时,就需要修改桶大小,但 Nginx 官网上明确建议它应该是 CPU Cache Line 的整数倍。

为什么要做这样的要求呢?就是因为按照 cpu cache line(比如 64 字节)来访问内存时,不会出现多核 CPU 下的伪共享问题,可以尽量减少访问内存的次数。

作者回复: 这里的原理其实与思考题是一致的,因为当所有bucket连续时,某个50字节的bucket一定会横跨2个cpu cache line,比如第2个bucket在内存上占用50-100字节,这样当CPU1访问第1个bucket时,会把第2个bucket的数据也载入,这样CPU2访问第2个bucket时,若第1个bucket发生变化,就会导致CPU2必须重新读入bucket。类似的,某个70个字节的bucket一定会占用到3个cpu cache line。 70: cpu访问时,第一次加载64个字节,包括第一个bucket和第二个bucket部分数据,第二次加载第二个bucket部分数据和第三个bucket,这样两次加载了3个bucket,当并发访问时,三个cpu访问三个bucket,如果有一个cache line数据发生变化,其他都2个cpu需要重新加载,导致缓存失效。

在用 Linux 操作系统,可以通过一个名叫 Perf 的工具直观地验证缓存命中的情况。执行 perf stat 可以统计出进程运行时的系统信息。

这是因为循环中有大量的 if 条件分支,而 CPU含有分支预测器。可以提前把这些指令放在缓存中,CPU 执行时就会很快。

**操作系统提供了将进程或者线程绑定到某一颗 CPU 上运行的能力。**如 Linux 上提供了 sched_setaffinity 方法实现这一功能,其他操作系统也有类似功能的 API 可用。当多线程同时执行密集计算,且 CPU 缓存命中率很高时,如果将每个线程分别绑定在不同的 CPU 核心上,性能便会获得非常可观的提升。

小结:

CPU 缓存分为数据缓存与指令缓存,对于数据缓存,我们应在循环体中尽量操作同一块内存上的数据,由于缓存是根据 CPU Cache Line 批量操作数据的,所以顺序地操作连续内存数据时也有性能提升。对于指令缓存,有规律的条件分支能够让 CPU 的分支预测发挥作用,进一步提升执行效率。对于多核系统,如果进程的缓存命中率非常高,则可以考虑绑定 CPU 来提升缓存命中率。

心得体会

  1. 这专栏十分深入,讲的也透彻。CPU的性能系统,和其实现的原理关系很重要。

工作体验

  1. 工作中有用到perf,但是并不是很懂,跟着这儿的代码去学习,一定收益匪浅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑马Redis | 基础篇

目录 一、SQL和NoSQL的区别 结构化与非结构化 关联和非关联 查询方式 事务 总结 二、Redis数据类型和命令 1、通用命令 2、数据类型 3、String类型 String的常见命令 Key结构 4、Hash类型 常见命令 5、List类型 6、Set类型 Set的常见命令 7、SortedSet类型 …

科研快报|PacBio全长扩增子测序破解蚊子肠道微生态与耐药性差异

论文题目&#xff1a;Differences in the intestinal microbiota between insecticide-resistant and -sensitive Aedes albopictus based on full-length 16S rRNA sequencing.期刊&#xff1a;Microbiologyopen影响因子&#xff1a;3.139发表时间&#xff1a;2021年1月研究背…

一个非常好用的中奖概率控制器

本文首发于微信公众号&#xff1a; 小蚂蚁教你做游戏。欢迎关注领取更多学习做游戏的原创教程资料&#xff0c;每天学点儿游戏开发知识。嗨&#xff01;大家好&#xff0c;我是小蚂蚁。今天分享一个非常好用的概率控制器&#xff0c;可以用于游戏中两种行为出现的概率控制。这个…

PHP MySQL 插入数据

使用 MySQLi 和 PDO 向 MySQL 插入数据 在创建完数据库和表后&#xff0c;我们可以向表中添加数据。 以下为一些语法规则&#xff1a; PHP 中 SQL 查询语句必须使用引号在 SQL 查询语句中的字符串值必须加引号数值的值不需要引号NULL 值不需要引号 INSERT INTO 语句通常用于…

《Linux Shell脚本攻略》学习笔记-第十三章

13.1 简介 现代Linux应用可以部署在专门的硬件、容器、虚拟机或是云端。 容器的缺点在于它以来于主机的系统内核。 虚拟机的防在于要占用大量的磁盘空间。 如果你想同时运行多个虚拟机&#xff0c;必须要有足够的内存来支撑各个虚拟机。否则&#xff0c;主机就不得不开始交换页…

SLS:基于 OTel 的移动端全链路 Trace 建设思考和实践

作者&#xff1a;高玉龙 (元泊)首先&#xff0c;我们了解一下移动端全链路 Trace 的背景&#xff1a;从移动端的视角来看&#xff0c;一个 App 产品从概念产生&#xff0c;到最终的成熟稳定&#xff0c;产品研发过程中涉及到的研发人员、工程中的代码行数、工程架构规模、产品发…

探索VGG网络与LeNet网络对精度的影响

1 问题在学习不同网络模型对实验精度的影响过程中&#xff0c;对我们的实验结果&#xff0c;各种参数数值的改变有何变化&#xff0c;有何不同。VGG-11网络与LeNet-5网络对精度和损失的影响研究。训练周期20其他参数都相同的方式来探索最终的精度。2 方法对于VGG-11网络&#x…

QTreeWidget 设置任意行背景色

设置任意某行&#xff0c;网上这类示例少&#xff0c;一般都是选中行、交替行、高亮行等设置。 比如我要将顶层节点的背景色修改一下。 方法1&#xff0c;先继承QTreeWidget,更改它的 drawBranches函数&#xff0c;在里面添加条件判断&#xff0c;然后根据需要设置颜色。 #i…

【计算机体系结构-01】指令集体系结构、微体系结构简介

1. “虚拟” to “现实” 首先可以看这张图片&#xff0c;下面的 Physics 所指的是我们的物理世界中看得见摸得到或者是客观存在的事物&#xff0c;而人类希望将自己的工作内容或者需求以某种方式映射到物理层面上&#xff0c;用物理变化带来的影响来完成人类工作内容。例如早期…

Python【r e】模块正则表达式[中]实战

正则表达式相关函数和符号用法&#xff1a;#正则表达式""".匹配任意某个字符[.]与转义字符的作用一致&#xff0c;表示匹配.,配合 &#xff0c;[.],即匹配一次或则多次. text . 或则 text ...2.从头匹配或者从左往右匹配re.match()"""import …

IDEA整合Docker,一键打包服务镜像与启动容器

尝试了IDEA整合Docker&#xff0c;坑有些多&#xff0c;但经过查阅资料都一一解决了&#xff0c;写了个案例&#xff0c;感觉这种方式确实要方便很多。下面来整理下步骤&#xff1a; 一、安装Docker 准备一台Linux&#xff0c;我这里用的是centos 7 mini 版&#xff0c;然后安…

内网穿透的概念及解决方案

1.什么是内网穿透 在外网的web请求可以转发到内网的本地服务 2.什么是内网&#xff1f;什么是外网&#xff1f; 内网(也叫局域网(Local Area Network&#xff0c;LAN))是在一个局部的地理范围内&#xff0c;一般可以是是几米内(比如家庭内网)&#xff0c;也可以是方圆几千米…

2023 年 10 大最佳 GIS 软件

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 GIS 是一个分析地理相关性…

【算法】拓扑排序

目录1.概述2.代码实现3.应用本文参考&#xff1a; LABULADONG 的算法网站 1.概述 &#xff08;1&#xff09;拓扑排序 (Topological Sort) 是指将有向无环图 G (V, E) 中所有顶点排成一个线性序列&#xff0c;使得图中任意一对顶点 u 和 v&#xff0c;若边<u, v> ∈ E(…

esp32 使用u8g2图形库 IIC驱动OLED

简介&#xff1a;使用U8g2库进行OLED的显示十分简单&#xff0c;首先要包含两个库&#xff0c;U8g2lib和Wire&#xff0c;后者是IIC通信需要用。对于IIC接口的OLED&#xff0c;需要在程序中指定一下引脚的接口定义&#xff0c;如果是SPI接口&#xff0c;可以参考U8g2库自带例程…

【Leetcode】NC31 第一个只出现一次的字符(牛客网)、面试题 01.01. 判定字符是否唯一

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 NC31 第一个只出现一次的字符 第一个只出现一次的字符_牛客题霸_牛客网【牛…

数据结构与算法(三)——顺序查找和二分查找

什么是查找 在一些数据元素中&#xff0c;通过一定的方法找出与给定关键字相同的数据元素的过程。 什么是列表查找 也叫线性表查找&#xff0c;从列表中查找指定元素 列表查找是一种算法&#xff0c;对应的自然就有输入和输出&#xff1a; 输入&#xff1a;列表、待查找元素…

【实际开发08】- Controller 层处理入参 , 可避免进去 impl 层

目录 1. 增 / 删 / 改 - 记录日志 , 查询不记录日志 2. 第一批次 : 参数校验 ( id、id1 id2 、&#xff1f;) 3. 增 / 改 dto 判空 , 实体类层 ( entity ) 进行处理 4. 通用修改 的 impl 层可供 ( status、普通 ) 使用 5. 入参优先级 : Json > Map > Javabean 1. …

终于有人将Session和cookie讲明白了!一节课彻底搞懂

1 引出session cookie session与cookie属于一种会话控制技术。常用在身份识别&#xff0c;登录验证&#xff0c;数据传输等。举个例子&#xff0c;就像我们去超市买东西结账的时候&#xff0c;我们要拿出我们的会员卡才会获取优惠。这时候&#xff0c;我们怎么识别这个会员卡真…

软考那些事儿,看这一篇就够了!

软考7个常见问题解答一、报考条件凡遵守中华人民共和国宪法和各项法律&#xff0c;恪守职业道德&#xff0c;具有一定计算机技术应用能力的人员&#xff0c;均可根据本人情况&#xff0c;报名参加相应专业类别、级别的考试。因此&#xff0c;计算机软件资格考试报名条件不设学历…