绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
Throughput, Bandwidth, Latency
2022-04-15 15:05:34

## 什么是时延Latency

Latency是一个动作所花费的时间,我们做一个操作,比如:copy一个1G大小的文件,花了10秒,我们说Latency=10秒

Latency要注意的几点:

### 不同角度Latency不同

比如,我们一个Redis Client客户端,给Redis服务器发送了一个Ping命令,我们发送时开始计算时间,等Redis返回一个Pong回应,我们按下秒表,看当前的时间。这两个时间的差值,就是这个动作的时延Latency。

如果是局域网内(通用网络,一般是千兆网或万兆网,注意:它是以bit为单位的),一般是200微妙(us)左右,于是,站在Redis Client角度,这个Latency等于200us。

但是,站在Redis服务器角度,它从开始看到这个Ping数据包,开始计时,然后写一个Pong字符串到操作系统的网络层(实际就是内存buffer),就算完成了(应该掐表了)。所以,Server角度,它的时间只消耗在内存操作。这个时间有多少,没有人测试过。但我有一个经验数据,请参考下文

单线程就比多线程性能差吗?不一定

假设慢的可能,是Server从主存Main Memoory,读一个数据,然后再向主存Main Memory写一个数据,总计就是200ns。但实际上,会比这少很多,因为读写时,数据很可能已经在CPU cache中,如果是L1 Cache,那么只要不到2ns。

但不管如何计算,上面的时间,都远小于客户端Redis Client所看到的200us,即至少有一千倍,甚至十万倍的差距。

那么时间花在哪里去了?

这个客户端和服务器之间的时间差异,被消耗在网络上了。就是数据包通过操作系统的TCP/IP系统栈,走网卡,再经过网络介质(比如铜缆或光缆、Hub或Switch),到达客户端的TCP/IP栈,后达到客户端的应用层,而且是一来一回,即Round Trip。

所以,记住:

时延是站在某个掐表计时的实体的角度,不同角度(或不同实体),得到的时间不同,即使是对于同一个动作

另外,站在Redis Client角度,它的时延Latency至少有两部分组成,一个是网络上消耗的时间,一个是Server实际内存操作的时间,但由上面的分析可以看出,大头是网络上的部分,所以,我们为简化分析,对于客户端程序的角度而言,经常将占主要时间的部分,当做整个动作的时延。

即对于上面这个例子:Redis Client的Ping命令处理的Latency = 网络Round Trip时延

### 时延不是定值,而是随机值,我们需要用概率来描述它

如果每次包消耗都是一模一样的200us,那就是好事。但如果你多测试几次,你会发现时延是不确定的,有时快,有时慢。

这是因为,在实际工作环境里,有很多因素影响这个时延。以上面这个为例,因为通信需要通过网络设备,比如一个Switch,但Switch不可能只为你这一个通信服务,它还需要服务其他客户,因此,有时,Switch就会忙些(甚至有时会打个小盹,比如计时器的影响),让时间或多或少有点变化。

但对于一个稳定的系统,一般而言,计算时间发送变化,但如果测试次数足够多,从统计角度看,它是一个比较稳定的值。

于是,我们用概率去描述这个统计稳定值,一般用P99, P50, Avarage这些指标来描述。P99就是99%的时间,低于当前这个值。Average,就是所有的次数的时间总和除于次数。

这样,我们才能用一个稳定的值作为标识,来替代并不稳定的单次Latency计时。

## 吞吐能力:Throughput

### Throughput和Latency的关系

什么是Throughput?Throughput,是我们做很多动作,同时,我们计算一段时间(比如:1秒)里完成的动作数。

以上面为例,我们发送一个Ping,返回一个Pong,作为一个动作。然后我们不停发送(但必须等到Pong回来后,才发下一个),然后我们计算1秒内,我们能够处理这样的动作有多少个。

数学好的同学,很快能算出,假设Average Latency = 200us,且很稳定的话,那么Throughput = 1秒/200us = 5000 op/秒。即Throughput是5K。

同样地,你会发现,Throughput也受上面的两个因素影响。

首先,这个Throughput是有角度的,这里的5K,是对于Redis Client客户端而言。而对于服务器,如果它能全速处理,假设每次都从L1 Cache操作数据,它的Throughput是 1秒/2ns,即0.5G(5亿次)。为什么服务器实际没有做到5亿的Throughput,是因为Redis Client发送的太慢,所以对于服务器而言,它大部分时间都在睡觉,只用自己能力的很小一部分来处理Ping命令。

同时,Throughtput也需要用统计概率来描述,幸运的是,我们用一段很长的时间,比如秒,来描述Throughput,所以,从统计角度,它一般是个稳定值。(记住:在计算机世界里,1秒是个相当长的时间)

那么,Throughput是否能简单地由Latency得来?

不可以。

因为存在并发。

我们假设有2个Redis Client同时向Server发送,我们会发现,它们的Latency不变。站在两个Redis Client一起的角度,我们认为Throughput增加了一倍,即10K。但如果看Latency,并没有变化,还是200us。

为什么?

因为服务器和网络设备,都能力足够强大,来一个请求,和两个请求一起到,它处理的时间都足够快,所以,并发并不降低服务器端的能力(因为服务器1秒可以处理5亿个Ping请求,两个并发的Redis Client合在一起,每秒也只能送上总和10K的请求),但包在网络上传递的时间(实际是服务器网络层和网络设备的故意等待时间),基本上就是200us。

所以,我们可以得到下面两个结论:

1. 对于并发,我们不能通过Latency简单换算成Throughput

2. 如果只有单客户单顺序执行(即得到个结果,才能发送第二个,否则就是并发),而且服务器处理的时间成本忽略不计,那么可以用Latecny换算成Throughput,而且是占在客户端角度

那我们能不能用 并发数 * 单个客户端的Throughput,来得到多个客户端的Throughput?

也不可以。

这是因为,如果并发的客户端形成的数据包,总数还比较小,那么上面的公式是成立的。当并发数足够大,这时,网络的数据量加大,服务器端就不能保证每个包的Round Trip都是200us,而是要更多时间(即单个客户端角度看,Latency加大了)。

所以,实际工作中,你需要做真正的测试,用不同的并发数,来测试整个系统的Throughput。有的并发数,是Throughput线性增长,即加大一倍的客户端,整个Throughput也加大一倍。有的并发数,则不能满足这个线性规律。甚至有时增大了并发数,整个Throughput还会降低(比如:某个数值触发了系统里某个部件的瓶颈)

### Throughput还有Pattern的差异

如果我们看一个磁盘,它的Throughput应该是每秒读出Read或写入Write的字节数。

有一个软件fio,可以很好地测试Throughput。但是,如果你给fio不同的参数,你会惊奇地发现,Throughput差别非常大。

我以一个例子来说明,你可以用下面的命令来进行测试。

我这里测试的是磁盘Write,为了保证数据数据落盘(即不丢失数据),每次请求完,都要fsync。

下面是每写一个block size为4K(--bs=4k),就fsync一次

fio --name=w --rw=write --ioengine=sync --direct= --fsync=1 --end_fsync=1 --size=200M --bs=4k;

在我的Mac机器上,输出是:Throughput = 2.8MB/s

然后改为每写一个block size为1024K(--bs=1024k),就fsync一次

fio --name=w --rw=write --ioengine=sync --direct= --fsync=1 --end_fsync=1 --size=200M --bs=1024k;

在我的机器上,这次输出是:Throughput = 191MB/s

这里有60多倍的差别。你可以在自己的机器上测试,因为每个机器的SSD磁盘的特性不一样,得到的数字和倍数会偶差别,但都会是一个很大的倍数。

也就是说,SSD面对不同的pattern(即不同的block size),表现的Throughput有可能有巨大的差别。

### Throughput有效性的差别

还是以磁盘为例,对于SSD磁盘,其小读/写的单位是4K。即我们即使每次读1K的数据,它也要每次读出至少4K数据。所以,假设我们每次都读1K的内容,即使磁盘能达到Throughput=400MB/s,但我们客户端角度看,实际的有效值只有100MB/s。

站在磁盘角度,其Throughput是400MB/s,但站在客户端角度,它只能看到吞吐Thourghput是100MB/s。

我们很多存储在磁盘的数据结构,不管是B+树,还是LSM树,都存在读写放大。

比如:对于LSM树,我们即使有效地写入了100M/B的Throughput,它后台还需要做compaction,针对这每秒的100M的数据进行多层压缩,这就是附加的读写。我们假设写放大是10倍,那么占在客户端角度,如果我们想达到100MB/s的Throughput,我们就需要磁盘至少能支持1GB/s的Throughput。

## 带宽:Bandwidth

哪什么是Bandwidth?

Bandwidth,就是站在某个硬件(或部件,但一般不会是客户端角度),在某个Pattern下,同时有效性为的情况下,能达到的大的Throughput。

所以,当你搭建系统时,购买或选择硬件时,会读到其产品说明书,开始的广告数字,都是Bandwidth。

但实际工作中,你要注意:这个Bandwidth,并不是你可以简单推算你的应用程序的Throughput,你需要清楚,你的Pattern是否匹配硬件,你的数据结构和系统架构,是否的利用了硬件。

我们需要在生产环境中,尽可能利用好硬件,特别是瓶颈硬件的Bandwidth,让自己的Pattern和硬件匹配,同时有效性尽可能高。

各个硬件的Bandwidth不同,如上例中,对于内存,其Bandwidth可以到100GB/s左右,对于不同的网卡,其Bandwidth一般是1Gb/s、10Gb/s、25Gb/s、100Gb/s,而对于SSD磁盘,有高有低,我看到有宣传超过1GB/s的SSD盘(但我自己从没有用过)。

但一般而言,磁盘是慢的,上面的几个数字也能推算出。

一个系统的Throughput,像一桶水一样,是由短的那个板决定容量。所以,我们需要特别关注慢的硬件,也就是磁盘。同时,我们要用好Pattern和有效率,尽量使整个系统(也就是客户端角度)Throughput去靠近这个Bandwidth。

## 参考

我自己比较关注磁盘的特性,做了一些实验,详细可参考:

hub.fastgit.org/szstonee
https://lee/SSDInternal/blob/master/scenario.md


分享好友

分享这个小栈给你的朋友们,一起进步吧。

分布式思考和实践
创建时间:2022-04-14 14:15:30
关于分布式在数据库领域的应用的一些思考以及一些程序应用的开发
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • szstonelee
    栈主

小栈成员

查看更多
  • miemieMIA
  • LCR_
  • jinchuan
  • MrSun
戳我,来吐槽~