你应该了解哪些延迟数字?
本文内容主要参考《Which latency numbers should you know?》
请注意这些不是准确的数字。它们基于一些在线基准(Jeff Dean 的延迟数 + 一些其它来源)。
CPU 寄存器:纳秒级
CPU 寄存器的访问时间非常短,通常只需要 1 到 2 个时钟周期(约为纳秒级)。
注:
一个 CPU 时钟周期是指 CPU 中的一个基本操作所需要的时间,通常是由 CPU 内部时钟的一个脉冲信号驱动的。它的实际时间取决于 CPU 的时钟速度,以及 CPU 设计中的其他因素。
在当前的计算机系统中,大多数 CPU 时钟速度都在几个 GHz(千兆赫)到几十 GHz 之间,即每秒钟可以执行几个亿个时钟周期。具体来说,一个 3.0 GHz 的 CPU 时钟周期大约是 0.33 纳秒(即 330 皮秒)左右。
L1 和 L2 高速缓存:1-10 纳秒
例如:它们通常内置于微处理器芯片中。除非你直接处理硬件,否则你可能不需要担心它们。
L2 缓存的访问时间通常为 4 到 12 个时钟周期,L3 缓存的访问时间通常为 10 到 40 个时钟周期。
L3 共享缓存:10~100 纳秒
RAM 存储器访问:100 纳秒
例如:从内存中读取数据需要约 100 纳秒。Redis 是一个内存数据存储库,因此从 Redis 读取数据需要约 100 纳秒。
System Call 系统调用:100~1000 纳秒
系统调用延迟是指从程序发起系统调用到操作系统完成调用并将控制返回给程序的时间。系统调用是用户级程序和操作系统之间的接口,它们允许程序请求操作系统提供服务,例如读写文件、创建进程或分配内存。
系统调用延迟是一个重要的性能指标,因为它对系统的整体性能有重要影响。系统调用延迟的大小取决于多种因素,包括操作系统的设计、运行操作系统的硬件以及系统的负载。
进程间上下文切换:1~10 微妙
进程间上下文切换是指在多任务操作系统中,当 CPU 从一个进程切换到另一个进程时,需要保存当前进程的状态(包括寄存器值、程序计数器等信息)并加载新进程的状态。这个过程被称为上下文切换。
在多任务操作系统中,多个进程可以同时运行,每个进程都有自己的程序代码和数据,它们共享计算机的 CPU、内存等资源。当操作系统需要切换到另一个进程时,必须先保存当前进程的状态,然后加载另一个进程的状态。这个过程需要花费一定的时间和资源,并且可能会影响系统的性能。
进程间上下文切换的主要影响因素包括:
进程数量:当系统中运行的进程数量增加时,进程间的上下文切换次数也会增加,从而导致系统开销增加。
进程切换频率:如果系统需要频繁地进行进程切换,例如在 I/O 密集型应用中,进程间上下文切换的开销会更大。
硬件性能:系统的 CPU、内存等硬件性能也会影响进程间上下文切换的开销。当 CPU 处理器速度快、内存带宽高等硬件性能好时,上下文切换的时间会更短。
为了降低进程间上下文切换的开销,可以采用以下策略:
减少进程切换次数:尽量减少进程切换的次数,例如通过线程池、异步 I/O 等技术来避免进程的频繁切换。
调整进程优先级:调整进程的优先级,使高优先级的进程优先执行,从而减少进程切换的次数。
优化进程调度算法:优化进程调度算法,使得系统可以更好地利用 CPU 资源,从而减少进程切换的开销。
提高硬件性能:提高 CPU 处理器速度、内存带宽等硬件性能,可以减少进程间上下文切换的开销。
通过 1 Gbps 网络发送 1K 字节:10 微秒
例如:从 Memcached 通过网络发送 1KB 的数据大约需要 10 微秒。
NGINX 单次 HTTP 请求处理:10-100 微秒
从 SSD 读取:100 微秒
SSD 读取是指从发出读取请求到 SSD 返回读取数据的时间,它与许多因素有关。
存储介质类型:SSD 使用的存储介质是闪存芯片,读取延迟时间比机械硬盘要短得多。
控制器性能:SSD 的控制器负责读取和写入数据,控制器的性能也会影响读取延迟。高性能的控制器可以使 SSD 的读取延迟更短。
数据分布:当 SSD 的存储空间使用率较高时,读取数据的延迟时间可能会增加,因为 SSD 需要搜索和整理数据。
例如:RocksDB 是一个基于磁盘的 K/V 存储,因此在 SSD 上的读取延迟约为 100 微秒。
SSD 的访问时间通常为 0.05 到 0.2 毫秒(即 50 到 200 微秒),与内存响应时间的比例为 1:500 到 1:100。
数据库插入操作:1 毫秒
例如:PostgreSQL 提交可能需要 1 毫秒。数据库需要存储数据,创建索引和刷新日志。所有这些操作都需要时间。
从 HDD 读取:10~100 毫秒
机械硬盘的读取响应时间是指从发出读取请求到硬盘返回读取数据的时间。它包括两个方面:寻道时间和数据传输时间。
寻道时间:当发出读取请求后,磁头需要移动到目标扇区的磁道上进行读取操作,这个过程就是寻道时间。寻道时间取决于磁头需要移动的距离和硬盘的寻道速度,通常在 2~20ms 之间。
数据传输时间:数据传输时间指的是从磁盘上读取数据到磁盘缓存中,然后通过总线传输到主存储器中的时间。数据传输时间通常比寻道时间短得多,只需要几微秒到几十微秒的时间。
发送数据包:100 毫秒:
例如:如果我们有一个长距离的 Zoom 通话,延迟可能约为 100 毫秒。
bcrypt 加密一个密码:100~1000 毫秒
bcrypt 是一种密码散列函数,用于加密用户密码。它是一个开源的密码哈希函数,最初由 Niels Provos 和 David Mazières 在 1999 年设计。bcrypt 采用的是 salted hash(加盐散列)的方式,它可以防止 rainbow table 攻击(彩虹表攻击)。
bcrypt 使用一个称为 blowfish 的密码算法来创建哈希。该算法需要两个参数:cost factor 和 salt。cost factor 定义了算法迭代的次数,因此可以控制哈希函数的计算时间。salt 是一个随机的字符串,用于增加哈希的强度和唯一性。由于 salt 是随机生成的,因此即使两个用户使用相同的密码,它们的哈希值也会不同。
在使用 bcrypt 哈希密码时,首先将密码和 salt 结合在一起,然后使用 blowfish 算法来生成哈希值。这个哈希值存储在数据库中,而 salt 存储在密码哈希值的一部分中。当用户输入密码时,系统将使用相同的 salt 和 blowfish 算法来计算哈希值,然后将其与数据库中存储的哈希值进行比较,以验证密码是否正确。
由于 bcrypt 哈希密码的复杂度很高,因此它很难被暴力破解。攻击者需要知道 salt 和 cost factor 才能破解密码。此外,由于 bcrypt 迭代次数是可调整的,因此系统管理员可以根据需要增加哈希函数的计算时间,从而提高密码的安全性。因此,bcrypt 常用于保护用户密码和敏感数据。
TLS 握手:250~500 毫秒
TLS 首次握手的流程通常如下:
客户端发送 Client Hello 消息,包含所支持的协议版本、加密算法、随机数等信息。
服务器发送 Server Hello 消息,包含所选择的协议版本、加密算法、随机数等信息。
服务器发送证书消息,包含公钥、证书链等信息,以供客户端验证。
客户端验证证书,生成并发送用于后续通信的随机数。
客户端发送 Client Finished 消息,通知服务器客户端已完成握手过程的前半部分。
服务器发送 Server Finished 消息,通知客户端服务器已完成握手过程的前半部分。
整个握手过程的时间延迟主要包括以下几个部分:
网络延迟:客户端和服务器之间的网络延迟会对握手时间产生影响。
证书验证:客户端需要验证服务器发送的证书是否合法,这个过程需要进行一些计算,会增加一定的时间延迟。
服务器计算:服务器需要对客户端发送的数据进行解密,生成密钥等操作,这也会增加一定的时间延迟。
握手过程中的往返次数:TLS 握手过程中涉及到多次网络往返,每次往返都需要一定的时间,这也会影响握手时间延迟。
TLS 首次握手的时间延迟通常在几百毫秒到数秒之间,具体时间取决于多种因素,如网络质量、计算机性能等。在握手过程中,尽可能地减少握手往返次数、减少证书验证所需的计算量等方法,可以有效地降低握手时间延迟。
重试/刷新间隔:1~10 秒
例如:在监控系统中,刷新间隔通常设置为 5~10 秒(Grafana 上的默认值)。
注:
1 纳秒=10^-9 秒
1 微秒=10^-6 秒=1,000 纳秒
1 毫秒=10^-3 秒=1,000 微秒=1,000,000 纳秒
评论