自己在极客时间课程、工作经验、技术博客的总结。

基本知识

时间量级

延时: 发生一次操作的时间均值

相对时间: 已一个cpu周期为1s的参照物,进行等比放大

事件 延时 相对时间比例
1个CPU周期 0.3ns 1s
L1缓存访问 0.9ns 3s
L2缓存访问 2.8ns 9s
互斥加锁 10ns 30s
L3缓存访问 12.9ns 43s
主存访问 120ns 6分钟
上下文切换 1微秒 1小时
固态硬盘I/O 50~160微秒 2~6天
旋转磁盘I/O 1~10ms 1~12月
互联网:从北京到深圳(2000km) 20ms 2年
TCP包重传 1~2s 105~317年
OS虚拟化系统重启 4s 423年

指标

  • IOPS: 每秒I/O 操作数
  • 吞吐量: 每秒数据量或操作量
  • 使用率
  • 延时
  • 饱和度

缓存

命中率越高越好。

算法:

  • 最近最常使用算法(MRU)
  • 最近最少使用算法(LRU)
  • 最常使用算法(MFU)
  • 最不常使用算法(LFU)
  • 不常使用算法(NFU)

缓存的状态:

  • 冷: 冷缓存时空的,或者填充无用信息。 命中率几乎为0
  • 热:填充常用数据,有着很高的命中率
  • 温:填充了部分有效数据,但命中率还没达到预期
  • 热度:缓存命中率

应用程序

技术

  • 选择合适的I/O尺寸
  • 用好缓存
  • 缓冲区
  • 轮询。 epoll替换poll
  • 并发和并行。使用自适应锁、读写锁
  • 非阻塞I/O
  • 处理器绑定。提高应用程序的内存本地性,减少内存I/O
  • 编译器优化
  • 垃圾回收(GC)
  • 线程池
  • 零拷贝
  • 协程
  • 数据结构、算法选择
  • 多线程替换多进程

CPU

基本知识

  • 处理器(socket):物理芯片
  • 多核:一个独立cpu实例。一个处理器可以包含多个cpu实例
  • 硬件线程(逻辑核):一个核上同时执行多个线程(包括intel的超线程HT)。

举例 如果一台计算机有两个处理器,每个处理器有 12 个核,而且采用了 HT 超线程(一般一个核两个HT),那么总的 CPU 数目就是 48,就是 2×12×2。这个数字 48,就是用监控软件实际看到的cpu数量。对于操作系统来说就是cpu0、cpu1、cpu2…cpu47.

概念

字长

处理器是围绕最大字长设计的–32位或者64位。更宽的字长意味着更好的性能。更宽的字长可能会在某些数据类型下因未使用的位而导致额外的内存开销,数据的大小也会因为指针大小的增加而增加,导致需要更多的内存I/O。但对于64位的x86架构来说,寄存器的增加核更有效的调用约定抵消了这些开销,因此64位的应用程序会比他们32位的版本跑得更快。如果软件被编译成较小的字长,它可能会慢很多。

多处理器和NUMA架构

现在的 CPU 普遍采用多处理器(Socket)来提高 CPU 性能,每个处理器都有自己可以直接访问的本地内存(Local Memory)。一般来讲,这里面每个处理器的性能和内存大小都是一样的。每个处理器也都可以访问其他处理器的内存,这些内存就相当于是外地 / 远程内存(Remote Memory)。当 CPU 处理器访问本地内存时,会有较短的响应时间(称为本地访问 Local Access)。而如果需要访问外地/远程内存时候,就需要通过互联通道访问,响应时间就相比本地内存变慢了(称为远端访问 Remote Access)。所以 NUMA(Non-Uniform Memory Access)就此得名。
采用多处理器和 NUMA 架构的主要原因,是提高整个 CPU 的并行处理性能。每一台服务器可以同时运行很多程序和进程。对每一个进程和线程而言,当它运行在某一个处理器上时,它所对应的内存使用默认的分配方案是——优先尝试在请求线程当前所处的处理器的本地内存上分配。如果本地内存不足,才会分配到外地 / 远程内存上去。

编译器优化

通过编译器选项(包括字长设置)来大幅改进;编译器更新以利用最新的cpu指令集进行优化。

CPU内存缓存

  • 一级指令缓存
  • 一级数据缓存
  • 转译后备缓存器(TLB)
  • 二级缓存
  • 三级缓存

其中L1、L2是核独享的,L3是处理器所有核共享的

缓存行(cache line)\缓存一致性

内存缓存系统中,已缓存行作为单位存储。x86处理典型的缓存大小是64字节。现代 CPU 为了保证缓存相对于内存的一致性,必须实时监测每个核对缓存相对应的内存位置的修改。内存可能会同时被缓存在不同处理器的多个cpu里,当一个cpu修改了内存,所有的缓存需要知道他们的缓存copy已经失效,应该被丢弃,这将导致核与核之间产生竞争关系,因为一个核对内存的修改,将导致另外的核在该处内存上的缓存失效,那么就需要从L3或从主存中重新获取数据,这将带来更大的I/O。在多线程的场景下就会导致这样的问题。当多线程修改看似互相独立的变量时,如果这些变量共享同一个缓存行,就会在无意中影响彼此的性能,这就是伪共享。

自愿上下文切换(VCX/cswch)

是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。

非自愿上下文切换(ICX/nvcswch)

是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。

性能指标

  • cpu负载情况
  • cpu利用率
  • 应用程序、线程的cpu利用率
  • cpu中断性能:软中断、硬中断、上下文切换

CPU性能常见问题表现

  • 中断:各个核中断不均衡,导致cpu超载或空闲
  • cpu超载:多核之间负载没有平衡;cpu做了无用功;应用程序设计需要优化;…
  • cpu空闲:太多内存操作,导致cpu停顿;太多的分支预测错误;…

分析工具

  • top
  • uptime
  • mpstat/pidstat
  • vmstat
  • perf

调优

提高最后一级缓存(LLC)命中率


perf stat -e LLC-loads,LLC-load-misses,LLC-stores,LLC-store-misses
  • 缩小数据结构,让数据变的紧凑(如c++ folly库F14ValueMap)
  • 用软件方式来预取数据

现代 CPU 其实一般都有硬件指令和数据预取功能,也就是根据程序的运行状态进行预测,并提前把指令和数据预取到缓存中。这种硬件预测针对连续性的内存访问特别有效。但是在相当多的情况下,程序对内存的访问模式是随机、不规则的,也就是不连续的。硬件预取器对于这种随机的访问模式,根本无法做出正确的预测,这就需要使用软件预取。软件预取就是这样一种预取到缓存中的技术,以便及时提供给 CPU,减少 CPU 停顿,从而降低缓存的不命中率,也就提高了 CPU 的使用效率。现代 CPU 都提供相应的预取指令,具体来讲,Windows 下可以使用 VC++ 提供的 _mm_prefetch 函数,Linux 下可以使用 GCC 提供的 __builtin_prefetch 函数。GCC 提供了这样的接口,允许开发人员向编译器提供提示,从而帮助 GCC 为底层的编译处理器产生预取指令。这种策略在硬件预取不能正确、及时地预取数据时,极为有用。但是软件预取也是有代价的。一是预取的操作本身也是一种 CPU 指令,执行它就会占用 CPU 的周期。更重要的是,预取的内存数据总是会占用缓存空间。因为缓存空间很有限,这样可能会踢出其他的缓存的内容,从而造成被踢出内容的缓存不命中。如果预取的数据没有及时被用到,或者带来的好处不大,甚至小于带来的踢出其他缓存相对应的代价,那么软件预取就不会提升性能。我自己在这方面的实践经验,有这么几条:软件预取最好只针对绝对必要的情况,就是对会实际严重导致 CPU 停顿的数据进行预取。对于很长的循环(就是循环次数比较多),尽量提前预取后面的两到三个循环所需要的数据。而对于短些的循环(循环次数比较少),可以试试在进入循环之前,就把数据提前预取到。

  • 去除伪共享缓存(缓存一致性问题)

这个问题的解决方案,是让每个元素单独占用一个缓存行,比如 64 字节,也就是按缓存行的大小来对齐(Cache Line Alignment)。具体方法怎么实现呢?其实就是插入一些无用的字节(Padding)。这样的好处,是多个线程可以修改各自的元素和对应的缓存行,不会存在缓存行竞争,也就避免了“伪共享”问题。

  • 进程和线程进行CPU绑定。避免切换cpu时L1、L2 缓存失效
  • cache line : 使用cache line每次至少连续读取64字节的特性,减少缓存访问。

cpu绑定、cpu独占

把进程绑定到一个或者多个 CPU 上,可以提高 CPU 缓存的命中率,减少跨 CPU 调度带来的上下文切换问题。
跟 CPU 绑定类似,进一步将 CPU 分组,并通过 CPU 亲和性机制为其分配进程。这样,这些 CPU 就由指定的进程独占,换句话说,不允许其他进程再来使用这些 CPU。

资源控制

使用 Linux cgroups 来设置进程的 CPU 使用上限,可以防止由于某个应用自身的问题,而耗尽系统资源。

优先级调整

使用 nice 调整进程的优先级,正值调低优先级,负值调高优先级。在这里,适当降低非核心应用的优先级,增高核心应用的优先级,可以确保核心应用得到优先处理。

中断的负载均衡

无论是软中断还是硬中断,它们的中断处理程序都可能会耗费大量的 CPU。开启 irqbalance 服务或者配置 smp_affinity,就可以把中断处理过程自动负载均衡到多个 CPU 上。

编译器选项

一般编译为64位而非32位进程;以及优化级别设置

方法论

“千万避免过早优化”。

过高德纳的这句名言, “过早优化是万恶之源”,过早优化不可取。因为,一方面,优化会带来复杂性的提升,降低可维护性;另一方面,需求不是一成不变的。针对当前情况进行的优化,很可能并不适应快速变化的新需求。这样,在新需求出现时,这些复杂的优化,反而可能阻碍新功能的开发。所以,性能优化最好是逐步完善,动态进行,不追求一步到位,而要首先保证能满足当前的性能要求。当发现性能不满足要求或者出现性能瓶颈时,再根据性能评估的结果,选择最重要的性能问题进行优化。

性能优化(应用程序、cpu)相关推荐

  1. 性能第二讲:性能优化-每个程序员都应该知道的数字

    性能第二讲:性能优化-每个程序员都应该知道的数字 文章目录 性能第二讲:性能优化-每个程序员都应该知道的数字 1.性能优化的重要性 2.性能指标 3.看这些数据的目的 4.总结 Action1:商品中 ...

  2. ue4渲染速度太慢_[UE4]性能优化指南(程序向)

    封面来源:A Cold Stop(Mixer 制作材质.UE4渲染 ) [UE4]性能优化指南(美术向)玄冬Wong:[UE4]性能优化指南(美术向)​zhuanlan.zhihu.com 内容都是处 ...

  3. Linux性能优化一:CPU优化以及平均负载的理解

    文章目录 前言: 什么是系统性能调优 到底怎么理解平均负载 它和CPU使用率的关系 平均负载多少合适 如何分析平均负载 平均负载升高的实战模拟 场景:CPU密集型进程 场景二:I/O密集型程序 前言: ...

  4. App性能优化——内存、CPU、耗电、启动时间指标获取分析

    最近公司要求对App进行性能优化.考虑到既然是优化性能,那首先要获取App的相关性能指标,比如: 内存占用.CPU利用率.App启动时间.App耗电量等情况,获取以上各指标后,才能针对性分析确定是否存 ...

  5. 笔记 :java性能优化 (from-JAVA程序性能优化)

    --From : JAVA程序性能优化 (葛一鸣,清华大学出版社,2012/10第一版) 1. java性能调优概述 1.1 性能概述  程序性能: 执行速度,内存分配,启动时间, 负载承受能力. 性 ...

  6. Android性能优化系列:CPU收敛优化(线程优化)

    文章目录 线程调度 线程调度的原理 线程调度模型 Android 的线程调度 线程调度小结 Android 异步方式汇总 Thread HandlerThread IntentService Asyn ...

  7. 网页性能优化实战之CPU拉满问题处理

    前言 今天测试小哥屁颠屁颠的找过来说查询会员信息这块访问速度很慢,之前没有问题,现在输入信息之后根本就没有反应.要等好好长时间才行.另外点击其他页面都是显示网络连接异常,感觉整个系统都会崩溃了.每次测 ...

  8. [UE4]性能优化指南(程序向)

    零散记录 GPUProfile来统计性能消耗的时候,在editor模式下不是很准,因为编辑器的消耗也算进去了,如果要用,最好以Game模式来查看. UE4不支持640X480的分辨率,如果在这个分辨率 ...

  9. Linux性能优化实战:CPU的上下文切换是什么意思(04)

    一.怎么查看系统上下文切换情况 通过前面学习我么你知道,过多的上下文切换,会把CPU时间消耗在寄存器.内核栈以及虚拟内存等数据的保存和回复上,缩短进程 真正运行的时间,成了系统性能大幅下降的一个元凶 ...

  10. 名为 cursor_jinserted 的游标不存在_性能优化技巧 - 程序游标

    很多算法都会产生落地的中间结果,从而影响性能,尤其是数据量较大的时候.这种情况下通常可用程序游标来避免数据落地,下面举例说明. 前半排序 计算目标:订单表原来已按时间排序,需要将数据按日期.产品去除重 ...

最新文章

  1. boot sprint 项目结构_京淘项目03 08.28
  2. 无法打开物理文件 X.mdf。操作系统错误 5:5(拒绝访问。)
  3. 【luogu 3375】【模板】KMP字符串匹配
  4. 【Android 逆向】Android 进程注入工具开发 ( SO 进程注入环境及 root 权限获取 | 进程注入时序分析 )
  5. 计算机编程英文术语,计算机编程英语词汇
  6. java数组转list,list转数组。
  7. 【今日CV 视觉论文速览】 04 Dec 2018
  8. android 颜色选择类
  9. Ubuntu 11.10 快捷键 gnome gFTP 服务器 vsftpd 程序 面板
  10. 工厂模式和策略模式区别
  11. 防火墙技术之--状态防火墙ASPF(2)
  12. linux openfire mysql_Linux系统安装openfire及其如何后台运行openfire
  13. 忘记linux密码怎么办?
  14. 如何保持福禄克CFP2-100-Q、OFP2-100-Q等光纤测试仪器的洁净?
  15. 中英文论文写作指导第一部分(文题、摘要、关键字)
  16. 你所不知道的VoIP通信技术?
  17. DDR SDRAM内存测试的一种官方方案(简单易懂)
  18. Laya1.0Matter.js案例之牛顿摆
  19. 如何提升w ndows10系统网速,Win10专业版系统网速慢的解决方法
  20. 2022讯飞——糖尿病遗传风险检测挑战赛解决方案

热门文章

  1. java简易制作图书查询系统
  2. * \r \r\n \t的区别,是什么意思
  3. 怎样调用通达信l2行情接口?
  4. 北京工业大学 大一C语言课程设计--四子棋(Bingo)(连子游戏)in TurboC 3.0
  5. OpenCV——轮廓
  6. 全球及中国工业级脱脂毛巾行业销售前景与渠道模式分析报告2022版
  7. Tensorrt下的Yolox部署
  8. 【知识蒸馏】使用CoatNet蒸馏ResNet图像分类模型
  9. 精彩对白:好想好想谈恋爱
  10. 计算机打印机设置在哪里,打印机设置在哪里 打印机设置在哪里进行设置