linux性能优化-磁盘I_O优化

1.文件系统

1.1.文件系统的工作原理

文件系统是在磁盘的基础上,提供了一个用来管理文件的树状结构。
接下来我们就看看Linux 文件系统的工作原理。

1.1.1索引节点和目录项

在 Linux 中一切皆文件 ,文件系统,本身是对存储设备上的文件,进行组织管理的机制
为了方便管理,Linux 文件系统为每个文件都分配两个数据结构,索引节点(index node)和 目录项(directory entry)。

  • 它们主要用来记录文件的元信息 和目录结构。索引节点,简称为 inode,用来记录文件的元数据,比如 inode 编号、文件大小、访问权限、修改日期、数据的位置等。索引节点和文件一一对应,它跟文件内容一样,都会被持久化存储到磁盘中。所以记住,索引节点同样占用磁盘空间。
  • 目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构。不过,不同于索引节点,目录项是由内核维护的一个内存数据结构,所以通常也被叫做目录项缓存。

文件数据到底是怎么存储的呢?

磁盘读写的最小单位是扇区,然而扇区只有 512B 大小,如果每次都读写这么小的单位,效率一定很低。所以,文件系统又把连续的
扇区组成了逻辑块,然后每次都以逻辑块为最小单元,来管理数据。常见的逻辑块大小为 4KB,也就是由连续的 8 个扇区组成。

注意:

  1. 目录项本身就是一个内存缓存,而索引节点则是存储在磁盘中的数据 ,Buw er和Cache缓存可以协调慢速磁盘
    与快速 CPU 的性能差异,文件内容会缓存到页缓存 Cache 中 ,这些索引节点自然也会缓存到内存中,加速文
    件的访问。
  2. 磁盘在执行文件系统格式化时,会被分成三个存储区域,超级块、索引节点区 和数据块区。超级块,存储整个文件系统的状态。索引节点区,用来存储索引节点。
    数据块区,则用来存储文件数据。

1.1.2.虚拟文件系统

**什么是虚拟文件系统VFS? **
为了支持各种不同的文件系统,Linux 内核在用户进程和文件系统的中间,又引入了一个抽象层,也就是虚拟文件系统 VFS(Virtual File System)。VFS 定义了一组所有文件系统都支持的数据结构和标准接口。这样,用户进程和内核中的其他子系统,只需要跟 VFS 提供的统一接口进行交互就可以了,而不需要再关心底层各种文件系统的实现细节。
为了更好地理解系统调用、VFS、缓存、文件系统以及块存储之间的关系 ,可以参考Linux 文件系统的架构图。
image.png
通过这张图,你可以看到,在 VFS 的下方,Linux 支持各种各样的文件系统,如 Ext4、XFS、NFS 等等。按照存储位置的不同,这些文件系统可以分为三类。
第一类是基于磁盘的文件系统,也就是把数据直接存储在计算机本地挂载的磁盘中。常见的 Ext4、XFS、OverlayFS等,都是这类文件系统。
第二类是基于内存的文件系统,也就是我们常说的虚拟文件系统。这类文件系统,不需要任何磁盘分配存储空间,但会占用内存。我们经常用到的 /proc就是一种最常见的虚拟文件系统。
第三类是网络文件系统,也就是用来访问其他计算机数据的文件系统,比如 NFS、SMB、iSCSI 等。
这些文件系统,要先挂载到 VFS 目录树中的某个子目录(称为挂载点),然后才能访问其中的文件。拿第一类,也就是基于磁盘的文件系统为例,在安装系统时,要先挂载一个根目录(/),在根目录下再把其他文件系统(比如其他的磁盘分区、/proc 文件系统、/sys 文件系统、NFS 等)挂载进来。

2.磁盘I/O工作原理

2.1.磁盘类型

2.1.1.根据介质不同分类

常见磁盘可以分为两类:机械磁盘和固态磁盘。
第一类,机械磁盘,也称为硬盘驱动器(Hard Disk Driver),通常缩写为 HDD。机械磁盘主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。在读写数据前,需要移动读写磁头,定位到数据所在的磁道,然后才能访问数据。
如果 I/O 请求刚好连续,那就不需要磁道寻址,自然可以获得最佳性能。这其实就是我们熟悉的,连续 I/O 的工作原理。与之相对应的,当然就是随机 I/O,它需要不停地移动磁头,来定位数据位置,所以读写速度就会比较慢。
第二类,固态磁盘(Solid State Disk),通常缩写为 SSD,由固态电子元器件组成。固态磁盘不需要磁道寻址,所以,不管是连续 I/O,还是随机 I/O 的性能,都比机械磁盘要好得多。
其实,无论机械磁盘,还是固态磁盘,相同磁盘的随机 I/O 都要比连续 I/O 慢很多,原因也很明显。

  • 对机械磁盘来说,我们刚刚提到过的,由于随机 I/O 需要更多的磁头寻道和盘片旋转,它的性能自然要比连续 I/O 慢。
  • 而对固态磁盘来说,虽然它的随机性能比机械硬盘好很多,但同样存在“先擦除再写入”的限制。随机读写会导致大量的垃圾回收,所以相对应的,随机 I/O 的性能比起连续 I/O 来,也还是差了很多。
  • 此外,连续 I/O 还可以通过预读的方式,来减少 I/O 请求的次数,这也是其性能优异的一个原因。很多性能优化的方案,也都会从这个角度出发,来优化 I/O 性能。

机械磁盘和固态磁盘还分别有一个最小的读写单位。

  • 机械磁盘的最小读写单位是扇区,一般大小为 512 字节。
  • 而固态磁盘的最小读写单位是页,通常大小是 4KB、8KB 等。

2.1.2.磁盘按照接口分类

按照接口来分类,比如可以把硬盘分为 IDE(Integrated Drive Electronics) 、 SCSI(Small Computer System Interface)、SAS(Serial Attached SCSI) 、 SATA(Serial ATA) 、 FC(Fibre Channel)等。
不同的接口,往往分配不同的设备名称。比如, IDE 设备会分配一个 hd 前缀的设备名,SCSI 和 SATA 设备会分配一个sd 前缀的设备名。如果是多块同类型的磁盘,就会按照 a、b、c 等的字母顺序来编号。

2.1.3.按照使用方式分类

把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列,也就是 RAID(Redundant Array of Independent Disks),从而可以提高数据访问的性能,并且增强数据存储的可靠性。
根据容量、性能和可靠性需求的不同,RAID 一般可以划分为多个级别,如 RAID0、RAID1、RAID5、RAID10 等。 RAID0 有最优的读写性能,但不提供数据冗余的功能。
而其他级别的 RAID,在提供数据冗余的基础上,对读写性能也有一定程度的优化。
最后一种架构,是把这些磁盘组合成一个网络存储集群,再通过 NFS、SMB、iSCSI 等网络存储协议,暴露给服务器使用。
在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是主、次设备号。主设备号用在驱动程序中,用来区分设备类型;而次设备号则是用来给多个同类设备编号。

3.IO栈

Linux的IO路径可能是Linux系统中比较复杂的模块,它直接决定了系统的性能。
Linux 存储系统的 I/O 栈全景图:
image.png
图片参考https://www.thomaskrenn.com/en/wiki/Linux_Storage_Stack_Diagram
根据这张 I/O 栈的全景图,我们可以更清楚地理解,存储系统 I/O 的工作原理。
应用程序
这没什么好说的,通过相关系统调用(如open/read/write)发起IO请求,属于IO请求的源头;
文件系统
应用程序的请求直接到达文件系统层。文件系统又分为VFS和具体文件系统(ext3、ext4等),VFS对应用层提供统 一的访问接口,而ext3等文件系统则实现了这些接口。另外,提高IO性能,在该层还实现了诸如page cache等功
能。同时,用户也可以选择绕过page cache,而是直接使用direct模式进行IO(如数据库)。
块设备层
文件系统将IO请求打包提交给块设备层,该层会对这些IO请求作合并、排序、调度等,然后以新的格式发往更底层。在该层次上实现了多种电梯调度算法,如cfq、deadline等。
SCSI层
块设备层将请求发往SCSI层,SCSI就开始真实处理这些IO请求,但是SCSI层又对其内部按照功能划分了不同层次;
SCSI高层:高层驱动负责管理disk,接收块设备层发出的IO请求,打包成SCSI层可识别的命令格式,继续往下发;
SCSI中层:中层负责通用功能,如错误处理,超时重试等; * SCSI低层:底层负责识别物理设备,将其抽象提供给高层,同时接收高层派发的scsi命令,交给物理设备处理。

4.性能指标

4.1.磁盘I/O性能指标

我们需要了解磁盘 I/O 性能监控的指标,以及每个指标的所揭示的磁盘某方面的性能。磁盘 I/O 性能监控的指标主
要包括:

  • 每秒 I/O 数( IOPS )

一次磁盘的连续读或者连续写称为一次磁盘 I/O, 磁盘的 IOPS 就是每秒磁盘连续读次数和连续写次数之和。

  • 吞吐量( Throughput)

指硬盘传输数据流的速度,传输数据为读出数据和写入数据的和。

  • 平均 I/O 数据尺寸

平均 I/O 数据尺寸为吞吐量除以 I/O 数目,该指标对揭示磁盘使用模式有重要意义。

  • 磁盘活动时间百分比( Utilization) %util

磁盘处于活动时间的百分比,即磁盘利用率,磁盘在数据传输和处理命令处于活动状态。

  • 服务时间( ServiceTime) svctm

指磁盘读或写操作执行的时间,包括寻道,数据传输等时间。

  • I/O 等待队列长度( Queue Length)

指待处理的 I/O 请求的数目,如果 I/O 请求压力持续超出磁盘处理能力,该值将增加。

  • 等待时间( Wait Time)

指磁盘读或写操作等待执行的时间,即在队列中排队的时间。

4.2.磁盘 I/O 观测

iostat 是最常用的磁盘 I/O 性能观测工具,它提供了每个磁盘的 使用率 、 IOPS 、 吞吐量 等各种常见的性能指标,当然,这些指标实际上来自 /proc/diskstats。
(1)命令格式:
iostat [参数][时间][次数]
(2)常用参数:
-c : 仅显示 cpu的状态
-d : 显示磁盘使用情况,不可以和 -c一起使用
-k : 默认显示的是读入读出的 block信息,以 KB 为单位显示
-m : 以 M 为单位显示
-t : 显示终端和CPU的信息
-x : 显示详细信息
(3)显示所有磁盘I/O的指标

[root@VM-12-2-centos ~]# iostat -d  -x 1
Linux 3.10.0-1160.71.1.el7.x86_64 (VM-12-2-centos)      01/22/2024      _x86_64_        (2 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00    11.35    0.19    9.91     5.03   130.58    26.86     0.02    2.34    7.47    2.24   0.98   0.99
scd0              0.00     0.00    0.00    0.00     0.01     0.00   103.09     0.00    0.61    0.61    0.00   0.33   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00    26.00    0.00    9.00     0.00   152.00    33.78     0.01    1.33    0.00    1.33   1.44   1.30
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

(4)磁盘每一列的含义如下:

  • Device: 磁盘设备名称。
  • rrqm/s: 每秒进行 merge 的读操作数目。
  • wrqm/s: 每秒进行 merge 的写操作数目。
  • r/s: 每秒完成的读I/O设备次数。
  • w/s: 每秒完成的写I/O设备次数。
  • rkB/s: 每秒读KB数(千字节/秒)。
  • wkB/s: 每秒写KB数(千字节/秒)。
  • avgrq-sz: 平均每次设备I/O操作的扇区数。
  • avgqu-sz: 平均I/O队列长度。
  • await: 平均每次设备I/O操作的等待时间(毫秒)。
  • r_await: 读操作的平均等待时间(毫秒)。
  • w_await: 写操作的平均等待时间(毫秒)。
  • svctm: 平均每次设备I/O操作的服务时间(毫秒)。
  • %util: 一秒中有百分之几的时间用于 I/O 操作,即设备利用率。

(5)需要注意的指标

  • %util ,就是我们前面提到的磁盘 I/O 使用率;
  • r/s+ w/s ,就是 IOPS;
  • rkB/s+wkB/s ,就是吞吐量;
  • r_await+w_await ,就是响应时间。
  • iostat 并不能直接得到磁盘饱和度。可以把观测到的,平均请求队列长度或者读写请求完成的等待时间,跟基准测试的结果进行对比,综合评估磁盘的饱和情况。

4.3.进程 I/O 观测

要观察进程的 I/O 情况,你还可以使用 pidstat 和 iotop 这两个工具。
(1)pidstat 观测I/O
pidstat 给它加上 -d 参数(使用-d选项,我们可以查看进程IO的统计信息 ),
你就可以看到进程的 I/O 情况,如下所示:

[root@VM-12-2-centos ~]# pidstat -d 1
Linux 3.10.0-1160.71.1.el7.x86_64 (VM-12-2-centos)      01/22/2024      _x86_64_        (2 CPU)

10:02:55 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
10:02:56 PM     0      8205      0.00      3.92      0.00  barad_agent
10:02:56 PM     0      8206      0.00      7.84      0.00  barad_agent
10:02:56 PM     0     12257      0.00      3.92      3.92  YDService

从 pidstat 的输出你能看到,它可以实时查看每个进程的 I/O 情况,包括下面这些内容。

  • 用户 ID(UID)和进程 ID(PID) 。
  • 每秒读取的数据大小(kB_rd/s) ,单位是 KB。
  • 每秒发出的写请求数据大小(kB_wr/s) ,单位是 KB。
  • 每秒取消的写请求数据大小(kB_ccwr/s) ,单位是 KB。
  • 块 I/O 延迟(iodelay),包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期。

(2)iotop 观测I/O
iotop是一个类似于 top 的工具,你可以按照 I/O 大小对进程排序,然后找到 I/O 较大的那些进程。 如果没有该命令,请通过 yum install iotop 进行安装
image.png

  • TID/PID:线程ID或进程ID,标识进行I/O操作的线程或进程。
  • PRIO:进程的优先级。
  • USER:进程或线程的所有者(用户名)。
  • DISK READ:从磁盘读取数据的速率,通常以KB/s或MB/s为单位。
  • DISK WRITE:写入磁盘数据的速率,同样以KB/s或MB/s为单位。
  • SWAPIN:进程交换(swap)进入的速率,表示进程从交换空间读取数据的频率。
  • IO:I/O等待的百分比,显示进程等待磁盘I/O操作完成的时间百分比。
  • COMMAND:进程的命令行名称或命令。
  • Total DISK READ:所有进程从磁盘读取数据的总速率。
  • Total DISK WRITE:所有进程写入磁盘数据的总速率。

5.性能工具

第一个维度,从文件系统和磁盘 I/O 的性能指标出发。换句话说,当你想查看某个性能指标时,要清楚知道,哪些工具可以做到
image.png
第二个维度,从工具出发。也就是当你已经安装了某个工具后,要知道这个工具能提供哪些指标。
image.png

6.磁盘I/O优化策略

6.1.应用程序优化策略

第一,可以用追加写代替随机写,减少寻址开销,加快 I/O 写的速度。
第二,可以借助缓存 I/O ,充分利用系统缓存,降低实际 I/O 的次数。
第三,可以在应用程序内部构建自己的缓存,或者用 Redis 这类外部缓存系统。
第四,需要频繁读写同一块磁盘空间时,可以用 mmap 代替 read/write,减少内存的拷贝次数。
第五,在需要同步写的场景中,尽量将写请求合并,而不是让每个请求都同步写入磁盘。第六,在多个应用程序共享相同磁盘时,为了保证 I/O 不被某个应用完全占用,推荐你使用 cgroups 的 I/O 子系
统,来限制进程 / 进程组的 IOPS 以及吞吐量。

6.2.文件系统优化策略

第一,你可以根据实际负载场景的不同,选择最适合的文件系统。比如 Ubuntu 默认使用 ext4 文件系统,而
CentOS 7 默认使用 xfs 文件系统。
第二,在选好文件系统后,还可以进一步优化文件系统的配置选项 。
第三,可以优化文件系统的缓存 。
3.磁盘优化策略
磁盘也是整个 I/O 栈的最底层。从磁盘角度出发,自然也有很多有效的性能优化方法
第一,最简单有效的优化方法,就是换用性能更好的磁盘,比如用 SSD 替代 HDD。
第二,我们可以使用 RAID ,把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列。这样做既可以提高数据的
可靠性,又可以提升数据的访问性能。
第三,针对磁盘和应用程序 I/O 模式的特征,我们可以选择最适合的 I/O 调度算法。比方说,SSD 和虚拟机中的磁
盘,通常用的是 noop 调度算法。而数据库应用,我更推荐使用 deadline 算法。
第四,我们可以对应用程序的数据,进行磁盘级别的隔离 。
第五,在顺序读比较多的场景中,我们可以增大磁盘的预读数据 。
第六,我们可以优化内核块设备 I/O 的选项。比如,可以调整磁盘队列的长度,以提升磁盘的吞吐量 。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

提升认知,推荐15个面向开发者的中文播客

前言 对于科技从业者而言,无论是自学成才的程序员,还是行业资深人士,终身学习是很有必要的,尤其是在这样一个技术快速迭代更新的时代。 作为一个摆脱了时间和空间限制的资讯分享平台,播客(Podcast&#x…

Parasoft C++Test安装指南_含独立版和插件版

文章目录 前言一、Windows环境下1. 安装独立版CTest2. 安装插件版CTest 二、Linux环境下1. 安装独立版CTest 总结 前言 CTest是Parasoft公司出品的一款可以针对C/C源代码进行静态分析、单元测试、集成测试的测试工具,在C/C白盒测试领域被广泛使用。本篇文章主要讲解…

黑马苍穹外卖学习Day10

文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发功能测试 WebSocket介绍入门案例 来单提醒需求分析代码开发 客户催单需求分析代码开发 Spring Task 介绍 cron表达式 入门案例 订单状态定时处理 需求分析 代码开发 新建一个task包里面编写代码…

140基于matlab的求解转子系统前三个临界转速和主振型的传递矩阵法转子系统的不平衡响应

基于matlab的求解转子系统前三个临界转速和主振型的传递矩阵法转子系统的不平衡响应。参数涉及等截面参数、材料参数、轮盘参数。程序已调通,可直接运行。 140 matlab临界转速及振型 (xiaohongshu.com)

Vue开发者工具是什么?有哪些?

Vue开发者工具是什么? Vue开发者工具是用于Vue.js开发的浏览器扩展,提供了许多有用的功能和工具,帮助开发者更轻松地开发和调试Vue.js应用程序。 Vue开发者工具的功能特点有哪些? 1、组件树视图:Vue开发者工具可以显…

【C++初阶】第二站:类与对象(上) -- 下部分

前言: 本章知识点: 类对象模型、 this 指针 专栏: C初阶 目录 类对象模型 如何计算类对象的大小 类对象的存储方式猜测 结构体内存对齐规则 this指针 this指针的引出 this指针的特性 C语言和C实现Stack的对比 C语言实现 C实现 类对象模型 …

JavaEE:多线程(2):线程状态,线程安全

目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入 死锁 死锁的解决方法 Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪:线程随时可以去CPU上执行,也包含在CPU上执行的…

SpringBoot 自定义Banner

SpringBoot自定义Banner SpringBoot项目启动的时候会输出一个Spring的图标。 思考🤔 它是在哪个环节的时候输出的呢?是否可以自定义图标呢? 源码分析 通常我们SpringBoot项目是通过SpringBoot.run(Appcation.class)启动的。 run() public Co…

【算法竞赛C++STL基础】栈,链表,队列,优先队列,map,set以及迭代器的用法

文章目录 1,前知——模板函数的实现2, hash 表1,定义2,ASCII码表3,咉射关系 3,迭代器4,STL关系1,stl 的基础关系2,stl 的分类1,相关分类2,相关简介顺序容器关联容器适配容器 3. STL 的相关函数的学习3.1 STL函数中都含…

buctoj——2024寒假集训 进阶训练赛 (五)

问题 A: 约瑟夫问题 题目描述 N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈;……输出依次出圈的人的编号。N,M由键盘输入。 输入 一行,包含两个正整数…

Linux 入门命令大全汇总 + Linux 集锦大全 【20240122】

文章目录 Linux 入门命令大全汇总Linux 集锦大全更多信息 Linux 入门命令大全汇总 别有一番风趣的alias 刚刚好合适的 apropos 命令 迷你计算器 bc 可看黄道吉日的 cal 全文可查看: Linux入门命令大全全文 Linux 集锦大全 linux终端中最漂亮的几款字体介绍及…

golang学习笔记——http.Handle和http.HandleFunc的区别与type func巧妙运用

文章目录 http.Handle和http.HandleFunc的区别http.Handle分析type func巧妙运用 http.HandleFunc分析总结参考资料 http.Handle和http.HandleFunc的区别 http.Handle和http.HandleFunc的区别体现了Go语言接口的巧妙运用 下面代码启动了一个 http 服务器,监听 808…

深入理解C语言(2):字符、字符串与内存函数

文章主题:字符、字符串与内存函数🌏所属专栏:深入理解C语言📔作者简介:更新有关深入理解C语言知识的博主一枚,记录分享自己对C语言的深入解读。😆个人主页:[₽]的个人主页&#x1f3…

jdk17新特性——Switch表达式增强

目录 一、Switch表达式增强示例一1.1、传统的方式 case中变量赋值示例1.2、jdk17 case中变量赋值示例 二、Switch表达式增强示例二2.1、传统的方式 case中值匹配多个示例2.2、jdk17 case中值匹配多个示例 三、Switch表达式增强示例三3.1、传统的方式 case中需要多行业务代码示例…

React-Native项目矢量图标库(react-native-vector-icons)

系列文章目录 React-Native环境搭建(IOS)React-Native项目 — 关于IOS知识储备React-Native项目工程搭建(开发模板搭建)React-Native项目矢量图标库(react-native-vector-icons) 目录 系列文章目录前言一、…

斐波那契查找

斐波那契查找 概述步骤代码示例输出结果 概述 斐波那契查找是一种基于斐波那契数列的查找算法,用于在有序数组中查找目标元素的位置。与二分查找类似,斐波那契查找也是一种分治算法,它通过比较目标值与数组的中间元素来确定下一步的查找范围…

C++版QT:鼠标事件

鼠标常用的事件可以说有一下几种&#xff1a;鼠标按下、鼠标移动、鼠标移动、鼠标双击和鼠标滚轮事件。 当你想使用他们&#xff0c;需要包含头文件&#xff1a;#include <QMouseEvent> 需要对鼠标事件进行处理时&#xff0c;通常要重新实现以下几个鼠标事件处理函数&a…

设备对象(DEVICE_OBJECT)

设备对象(DEVICE_OBJECT) 每个驱动程序会创建一个或多个设备对象&#xff0c;用DEVICE_OBJECT数据结构表示。每个设备对象都会有一个指针指向下一个设备对象&#xff0c;因此就形成一个设备链。设备对象链的第一个设备是由DRIVER_OBJECT结构体中指明的。设备对象保存设…

UI自动化中的option选项配置

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

《WebKit 技术内幕》学习之七(2): 渲染基础

2 网页层次和RenderLayer树 2.1 层次和RenderLayer对象 前面章节介绍了网页的层次结构&#xff0c;也就是说网页是可以分层的&#xff0c;这有两点原因&#xff0c;一是为了方便网页开发者开发网页并设置网页的层次&#xff0c;二是为了WebKit处理上的便利&#xff0c;也就是…