常见指标 ######## 单位:: 1ns 纳秒(nano second) 1us = 1,000ns 微秒(micro second) 1ms = 1,000us 毫秒(milli second) 1s = 1,000ms 秒 响应指标 ======== 常见响应指标 ------------ .. figure:: https://img.zhaoweiguo.com/knowledge/images/cores/tunes/indicator1.png 每个程序员都应该知道的延迟数字 《Teach Yourself Programming in Ten Years》:: 1. fetch from L1 cache memory(从一级缓存中读取数据): 0.5 nanosec 2. branch misprediction(分支预测失败): 5 nanosec 3. fetch from L2 cache memory(从二级缓存获取数据): 7 nanosec 4. Mutex lock/unlock(互斥加锁 / 解锁): 25 nanosec 5. fetch from main memory(从主内存获取数据): 100 nanosec 6. send 2K bytes over 1Gbps network(通过 1G bps 的网络发送 2K 字节): 20,000 nanosec = 20us(微秒) 7. read 1MB sequentially from memory(从内存中顺序读取 1MB 数据): 250,000 nanosec = 250us 8. fetch from new disk location (seek)(从新的磁盘位置获取数据(寻道)): 8,000,000 nanosec = 8ms(毫秒) 9. read 1MB sequentially from disk(从磁盘中顺序读取 1MB 数据): 20,000,000 nanosec =20ms 10. send packet US to Europe and back(从美国发送一个报文包到欧洲再返回): 150 milliseconds = 150,000,000 nanosec 用户体验 -------- * 交互响应时间 超过 100~200ms 就被认为是不好的 * 用户体验来说:: 1. 0~200ms,用户无感知 2. 200ms~1s,稍感延迟,可接受 3. 1~Ns,明显等待,越长体验越差 操作系统 -------- 按页读取:: 一页大小通常是 4KB,这个值可以通过 getconfig PAGE_SIZE 命令查看 一次会读一页的数据。如果要读取的数据量超过一页的大小,就会触发多次 IO 操作 我们在选择 m 大小的时候,要尽量让每个节点的大小等于一个页的大小。读取一个节点,只需要一次磁盘 IO 操作。 :: 高速缓存的读取时间可能是 0.5ns 而内存的访问时间可能是 50ns 并发指标 ======== 常见并发指标 ------------ * redis: 并发请求数也就每秒 3-5 万(基于 Reactor 模式) * nginx 负载均衡性能是 3-5 万左右(基于 Reactor 模式) * mc 的读取性能 3-5 万左右(基于 Reactor 模式) * LVS 的性能是十万级,据说可达到 80 万 / 秒 * F5 性能是百万级,从 200 万 / 秒到 800 万 / 秒都有 * kafka 号称百万级, 百万级是集群性能 * zookeeper 写入读取 2 万以上 * http 请求访问大概在 1.5-2 万左右(HTTP get 操作访问一个简单页面测试结果) * MySQL 的 TPS 和写入的数据有关:: 写入 k/v 数据,主键存储 key,上万TPS 读取 k/v 数据,可以达到10万 QPS mysql 官网 benchmarks: https://www.mysql.com/why-mysql/benchmarks/ 单机 32users 并发只读近 40w+ qps,读写 10w+ qps 说明: 这个数据有误导性,要看具体的 SQL 语句和表结构,实际应用中一般不可能这么高 这个数据是简单的 k/v 数据 * NoSQL量级一般都是上万,但和测试硬件测试用例相关 * 业务系统一个 TPS 接口的请求时间 10~50ms 是比较合理的,QPS 5~20ms 是比较合理的 理想情况下,性能测试的时候,CPU 能压到 80% 以上,此时的 TPS/QPS 就是峰值,如果 CPU 没压满,指标就上不去,就可能有优化的空间。 如果是业务系统,由于业务复杂度差异很大,有的每秒 500 请求可能就是高性能了,因此需要针对业务进行性能测试,确立性能基线,方便后续架构设计做比较 http 相关性能:: Spring Boot 基于 HTTP 协议的,HTTP 协议本身的解析非常耗性能 我们之前实测 Hello world,16 核或者 32 核的机器,单机 TPS 也就 1.5 万左右(核数增加对性能作用不大) * 一般把日活转换为 pv,然后按 pv 计算 QPS * 单台服务器性能一般是:: 企业用的线上物理服务器,如: 16 核 16g 32 核 16G 与时俱进,现在基本都是 32 核 48g 内存 云主机的性能可以按照同配置的物理机 80% 的性能来估算 服务器 ---------- * 一台机器最多开65535个 port, 其中压测可用的 port 是 ``32768~65535`` ,也就是每个兵团的士兵可达到 ``32768`` 个 * 单机可以支持: C100K, C1000K, C1M, C10M, C20M * 单进程文件句柄最大可以设置:: 即: 单个进程可分配的最大文件数 在我们使用ulimit或limits.conf来设置时,如果要超过默认的1048576值时需要先增大nr_open值 注: Linux 内核 2.6.25 以前,在内核里面宏定义是 1024*1024,最大只能是 100w(1048576) 如果 Linux 内核大于 2.6.25 则可以设置更大值 Java ---- 经过 Netty 封装相比Java 原生 NIO,大约有 10% 的性能损耗:: 在 1K 大小报文时 原生的 Java NIO 在当时的测试环境所能达到 TPS(每秒事务数) 的极限大约 5 万出头, 而 Netty 在 4.5 万附近 增加了 RPC 的编解码后,TPS 极限下降至 1.3 万左右 加上不算简单的业务逻辑,能预期的单实例真实 TPS 也许只有 1 千 ~2 千 注: 极限,就是继续加压,但 TPS 不再上升,CPU 也消耗不上去,延时却在增加 内存, 磁盘指标 ============== * 一个TCP套接字连接占用的内存做分析,大概占4KByte 内存:: 单根 DDR4 内存的数据传输带宽最高为 34GB/s 工作频率最高可达 4266MHz 以 PC 为例:: Intel 386 时代服务器存储能力只有几百 MB Intel 奔腾时代服务器存储能力可以有几十 GB Intel 酷睿多核时代的服务器可以有几个 TB 估算一下,给这 1 亿张图片构建散列表大约需要多少台机器:: 1. 假设我们通过 MD5 来计算哈希值,那长度就是 128 比特,也就是 16 字节 2. 文件路径长度的上限是 256 字节,我们可以假设平均长度是 128 字节 3. 如果我们用链表法来解决冲突,那还需要存储指针,指针占用 8 字节 所以,散列表中每个数据单元就占用 152 字节(这里只是估算,并不准确) 假设一台机器的内存大小为 2GB,散列表的装载因子为 0.75, 那一台机器可以给大约 1000 万(2GB*0.75/152)张图片构建散列表 所以,如果要对 1 亿张图片构建索引,需要大约十几台机器。 在工程中,这种估算还是很重要的, 能让我们事先对需要投入的资源、资金有个大概的了解,能更好地评估解决方案的可行性。 :: 内存的访问速度是纳秒级别的 磁盘访问的速度是毫秒级别的 从内存中读取所花费时间的上万倍,甚至几十万倍 磁盘 ---- .. figure:: https://img.zhaoweiguo.com/uPic/2023/10/EGdEN9.png 说明:: PCI Express主要用于连接高速设备,如显卡、声卡等 使用点对点串行连接,每个设备都有自己的专用连接,不需要向整个总线请求带宽,而且可以把数据传输率提高到一个很高的频率,达到PCI所不能提供的高带宽。 SATA 3.0则主要用于连接存储设备,如硬盘和光驱 SATA 3.0 的接口:: 带宽是 6Gb/s(转Byte=768MB) PCI Express 的接口:: 在读取的时候就能做到 2GB/s 左右,差不多是 HDD 硬盘的 10 倍 在写入的时候也能有 1.2GB/s IOPS 也就是在 2 万左右 HDD 硬盘(机械硬盘):: 5400转笔记本硬盘平均读写速度大致在60-90MB这个区间 7200转台式机硬盘大致在130-190MB区间 10000转和15000转台式机硬盘数据不详 数据传输率,差不多在 200MB/s 以内 IOPS 通常在 100 左右 随机读取磁盘上某一个 4KB 大小的数据: 在随机读写的时候,数据传输率也只能到 40MB/s 左右,是顺序读写情况下的几十分之一 响应时间指标:: SSD 硬盘: 几十微秒 HDD 硬盘: 几毫秒到十几毫秒 传输速度 -------- * 线路传输的速度是毫秒级别:: 1. 同一机房: 内部能够做到几毫秒; 2. 同城异地: 几毫秒~十几毫秒(距离上一般大约就是几十千米) 3. 跨城异地: 几十甚至上百毫秒(几百、上千千米) 例如: 从广州机房到北京机房,稳定情况下 ping 延时大约是 50ms,不稳定情况下可能达到 1s 甚至更多 4. 跨国异地: 几秒钟 :: 光速真空传播大约是每秒 30 万千米 在光纤中传输的速度大约是每秒 20 万千米 光速:C = 30 万千米 / 秒 光纤:V = C/1.5=20 万千米 / 秒 网速: 2017 年 11 月知名测速网站 Ookla 发布报告,全国平均上网带宽达到 61.24 Mbps, 千兆带宽下 10KB 数据的极限 QPS 为 1.25 万 QPS=1000Mbps/8/10KB 实例1: 北京到广州距离为2100多公里,即: 理想情况下,光纤在北京到广州传输需要0.21/20=0.01s=10ms 但传输中的各种网络设备的处理,实际还远远达不到理论上的速度 一般从广州机房到北京机房,稳定情况下 延时大约是 50ms 实例2: 地球到火星距离是 0.55~4 亿千米。近距离约为 5500 万公里,最远距离则超过 4 亿公里。 2021 年 5 月 15 日祝融号登陆的 9 分钟被称作 “恐怖 9 分钟,因为这9分钟我们是不可能操控探测器的。 原因是地球在与火星通讯的时候会有十几二十分钟的延迟。 这十几分钟延迟算法如下: 按光在真空中最快的30万km/s,距离5500-40000万km延时分别为: 5500/30 ~ 40000/30 = 183s ~ 1333s = 3分钟~22分钟 这是最理想的速度的延时。 pv/qps 计算 ----------- :: pv = 日活 * 人均点击次数 并发均值 = pv/86400 并发峰值 = 并发均值 * N :: 1. 响应时间(RT) 2. 并发数(Concurrency) 3. 吞吐量(TPS) 吞吐量 = 并发数 / 平均响应时间 * 最⼤吞吐量: 可⽀持的带宽 * 最⼤并发连接数: 每秒连接的总数量,体现并发处理连接的能⼒ * CPS: 每秒新建连接数:每秒新建连接的数量,体现处理新增连接的能⼒ * PPS: 每秒处理包量: 每秒钟转发的包量,体现包转发速率 * QPS: Query Per Second(每秒请求数,一般指读取,TPS) * TPS: Transactions Per Second(每秒事务数,一般指写入,QPS) * 并发数:同一时刻的接收的访问数量,时间单位一般用秒,也可以用分钟和小时,常见有并发请求数,并发连接数 * 日活:每日活跃用户数,指当天来访问过系统的用户,同一用户,无论用户访问多少功能和页面都只算一个用户 可靠性 ------ * 单机的可靠性大概是 100 天丢失一次数据,数据修复时间是 1 天(即可靠性是 2 个 9) * 单机可靠性只有两个 9 不是算出来的,统计出来的 tmp === UNIX 网络编程 ------------- * RTT在一个局域网上大约是几毫秒,跨越一个广域网则可能是数秒钟 参考 ==== * 伯克利大学的一个动态网页可以查看每年计算机中各类操作耗时、延迟的变化: https://colin-scott.github.io/personal_website/research/interactive_latency.html