论文悦读(5)——NVM文件系统之CtFS(FAST‘22)文件系统

news2025/5/13 1:55:51

CtFS(FAST'22)

    • 1. 背景(Background)
      • 1.1 NVM
      • 1.2 NVM文件系统
      • 1.3 快速索引方案
    • 2. 观察与动机(Observation & Motivation)
    • 3. CtFS设计与实现(Design & Implementation)
      • 3.1 系统概览(Architecture)
      • 3.2 文件系统结构(`ctU`)
      • 3.3 内核子系统(`ctK`)
      • 3.4 文件系统操作
      • 3.5 其他优化
      • 3.6 文件系统保护
    • 4. 评估(Evaluation)
      • 4.1 微基准测试
        • 4.1.1 追加写
        • 4.1.2 其他负载
        • 4.1.3 大页优化分析
      • 4.2 真实应用
      • 4.3 资源开销测试
      • 4.4 可拓展性
    • 5. 总结

导读:

  • CtFS最为核心的地方是利用持久化内存NVM的内存特性,构建了基于连续虚拟地址空间的NVM文件系统,从而可以通过硬件MMU快速索引。CtFS通过构建全局持久化页表(Persistent Page Table,PPT)来完成虚拟空间到NVM地址的映射。相比SCMFS,CtFS通过对虚拟空间进行精细化分以及pswap()技术保证文件的大小动态缩减(这是SCMFS所未提及的问题)。
  • CtFS的动机是发现现有的文件系统索引开销较大,因此使用硬件MMU加速索引可以基本避免索引的软件开销。这个Idea看起来在重庆大学提出的SIMFS中也是类似的思想。但相比于SIMFS,CtFS需要将PPT的部分拷贝到DRAM中,而SIMFS为每个文件部署Page Table,并且可以直接嵌入到进程Page Table中访问。但令人奇怪的是,CtFS并没有与SIMFS做对比,可能没有调研到SIMFS文件系统。
  • 总之,设计基于虚拟地址空间访问的NVM文件系统是个人看来比较有吸引力的工作,这既能够发挥NVM的存储性能,又能很好地利用NVM的内存特性。后续对NVM的研究中可以时常思考这一点。

1. 背景(Background)

1.1 NVM

以下内容为个人评述

商用NVM,Optane DCPMM宣布停产,这对于学术界或者工业界都不算一个好消息。NVM的研究是否还能继续?很多人开溜,又要去追CXL(CXL是一种新型互联标准,似乎可以为高速设备提供内存访问接口)。个人认为无论是CXL还是NVM其本意都是将存储器的大容量与内存的便捷高效访问结合起来。因此,在NVM上的研究可能可以迁移到基于CXL协议的设备上。其二,虽然Intel的Optane DCPMM停产,但是嵌入式领域还有大量NVM设备,例如:NOR Flash,这个设备支持字节级寻址,同时支持持久性保存。因此,对NVM的研究仍然是有意义的。后续的研究需要继续充分探索、挖掘NVM的特性。

1.2 NVM文件系统

文章将现有NVM文件系统划分为两个技术点

  • 使用DAX:EXT4-DAX、XFS-DAX、PMFS等
  • 用户态访问:ZoFS(见这里)、SplitFS(见这里)等

但是本文认为现有的这些文件系统都是基于树型索引,例如,为了将一个文件的offset转换为NVM上的块地址,需要使用软件方法便利查找树型索引,这对于快速PM设备来说会带来较大的开销。

1.3 快速索引方案

为了避免索引开销,可以使用连续分配的文件系统,即,文件的空间是连续的,知道文件数据的首地址后,做简单的加法就可以找到offset对应的数据块地址。但是,这种方案存在三个挑战:

  • 固定文件分配大小会产生内部碎片问题;
  • 可变文件分配大小会产生外部碎片问题;
  • 为支持连续空间,文件大小变化(尤其是增长)会带来严重的数据迁移问题;

仔细一想,这些问题其实与操作系统内存管理产生的问题一致。示意图如下

在这里插入图片描述

现有的解决方案有2种:

  • 只读文件系统
  • 基于连续虚拟地址的文件系统:SCMFS、SIMFS(原文没有)等。核心是保证虚拟内存的连续性,并通过硬件MMU做虚拟地址到NVM地址的翻译;

然而,CtFS认为现有的基于虚拟内存的方案只考虑了High-Level的设计,缺乏对真实实践的思考,例如:没有详细说明文件是如何分配以及更新的。事实上,SIMFS已经把这些问题考虑得比较清楚了。不过CtFS与SIMFS的解决方案很不同,本文不做赘述。

2. 观察与动机(Observation & Motivation)

CtFS主要针对EXT4-DAX和SplitFS进行观察,也对应于1.2节提到的两种类型的文件系统(DAX和用户态访问)。这里再回顾一下SplitFS,其搭建在EXT4-DAX之上,使用mmap()对NVM空间进行直接访问。具体来说,SplitFS的用户态库维护了一系列2MB的mmap()映射区域,这些映射区域属于一个在EXT4-DAX中创建的文件。为了访问SplitFS中文件的offset,SplitFS首先需要找到该offset在EXT4-DAX中对应文件的offset,然后再由EXT4-DAX通过搜索extent树来获取真实的NVM地址。

测试负载主要选择如下6种:

  • Append:向一个空文件中重复追加写4KB数据;
  • SWE(Empty):向一个空文件中顺序写入10GB数据。其中,每次利用pwrite()写入1GB数据;
  • SW/SR:顺序读写10GB数据,每次I/O量为1GB;
  • RR/RW:以4KB对齐方式在一个10GB文件中读写数据,数据读写总量为10GB(即总共2621440次)

测试结果如下:
在这里插入图片描述

其中,ext4ext4r分别对应于在连续分配和随机分配的文件上跑测试。连续分配的文件类似SWE。随机分配的文件以稀疏文件方式给出。二者最大区别在于extent的深度。连续分配的文件可以被extent更好地表示,随机分配的则需要更多的extent才能表示。例如,对于一个10GB的文件,连续分配只需要12个extents,而随机分配则需要256个extents。

可以看出来,ext4的内核部分索引时间占据较大,尤其是在Append、SWE、RW、RR负载下,主要因为这些负载IO次数较多,会造成较多extent树访问。SplitFS底层基于ext4索引,因此相应的负载也占据较大的内核索引延迟。

由此,CtFS进一步观察到索引带来的开销,构成了本文使用硬件MMU索引的动机。

3. CtFS设计与实现(Design & Implementation)

3.1 系统概览(Architecture)

CtFS是一个用户态文件系统,其在用户态访问元数据和数据。文件或目录被分配在连续虚拟内存空间中。相较于传统文件系统的从offset到NVM块地址索引,CtFS将该过程移交给MMU完成。具体而言,CtFS有如下4点设计目标:

  • POSIX兼容性:CtFS用户态文件系统基本需要通过提供POSIX兼容接口为应用使用;
  • 同步写入:CtFS保证写操作都是同步的,即fsync()在CtFS中没有啥作用;
  • 崩溃一致性:CtFS使用Redo Logpswap()(个人觉得比较类似COW)保证元数据和数据一致性。
  • 并发操作:使用读写锁保证并发操作;

与NOVA与SplitFS类似,CtFS同样提供sync模式与strict模式,前者不保证数据一致性,而后者保证数据一致性。下图显示了CtFS的基本架构。其中,Partition代表各文件占据的虚拟内存空间。

在这里插入图片描述

主要由用户态库ctU和内核子系统ctK构成。前者提供文件系统基本语义,后者提供虚拟内存相关实现。ctU在虚拟内存空间中管理文件系统结构,ctK提供虚拟地址到NVM物理地址的映射。映射由存储在NVM上的Persistent Page Table(PPT)完成。当ctU发生page fault时,ctK就会查询PPT并将对应映射插入内核页表中。当PPT中的映射无效后,ctK就会从内核页表中移除相应映射,并刷下相应的TLB项。

3.2 文件系统结构(ctU

ctU主要用于管理连续的虚拟地址空间。它采用一种类似伙伴分配器的方式进行空间的管理。如下图所示。ctU将虚拟地址空间划分为L0-L910个大小层级。L0是以4KB为单位的PartitionL9是以512GB为单位的Partition。每个层级之间大小相差8倍(而非伙伴分配器的2倍),从个人角度来看,这样的设计对文件系统使用更友好。

  • 文件管理:CtFS总是分配比文件大小更大的Partition即可,例如,为1KB的文件分配4KB的PartitionL0层级),这样子每个文件都拥有连续的虚拟地址空间;

  • 文件系统布局:下图显示了CtFS在虚拟空间中的布局结构。CtFS将1TB的连续虚拟地址空间划分为两个L9Partition,第一个Partition被用于存储文件系统元数据,例如:超级块、索引节点(Inode)等。Inode中存放着该文件数据对应的虚拟地址起始地址。第二个Partition则被用于存放文件系统的数据存储。

    每个Partition有三种状态,分别是:已分配(Allocated,A)、已划分(Partitioned,P)以及空(Empty,E)。为文件分配的Partition被标记为A。被标记为PPartition被划分为8个下一层级Partition。例如,图中,一个L9Partition被分成了8个L8Partition,并且第1、3个L8的Partition仍然处于划分状态P,这意味着这两个L8Partition将被继续划分为2$\times$8个L7Partition。以此类推。
    在这里插入图片描述

    作者进一步总结了这种层级架构的性质:

    • 对于任何Partition,其父亲Partition必须处于被划分的P状态(容易理解)
    • 对于任何Partition中的地址,其父亲Partition也含有该地址(因为是父亲划分下来的)
    • 只要L9Partition能够与512GB对齐,则任何子Partition的起始地址都可以与Partition的大小对齐
  • Partition头(Header):每个P状态的Partition都需要一个头结构来记录元数据信息,例如Partition的状态。ctU将头结构存储在每个Partition对应的第一个4KB页面。ctU使用2个比特来表示Partition的三个状态。为了加速Partition分配,头结构会含有一个空闲等级字段记录最高的有空闲Partition的层级。例如,上图中L9 Partition的空闲等级为8,因为其子Partition(即L8)有至少一个空闲Partition(共三个L8空闲Partition);L8 Partition的空闲等级为7,因为其子Partition(即L7)有2个空闲的Partition。据此,如果需要分配一个等级为LNPartitionctU就会避免查找空闲等级小于N的且状态为PPartition

    因为ctU将头结构放在每个P Partition对应的第一个页面。因此,第一个页面永远不能为A状态,因为第一个被划分出来的Partition应该继续被划分以为文件分配空间。换句话说,含有头结构的Partition的所有第一个子Partition将一直处于P状态直到无法划分为止(L0-L3被定义为不可再分)。ctU将每个层级的头结构都存储在同一个页面中。L3 Partition的空间可以被分成512个L0 Partition、64个L1 Partition以及8L2 Partiton,这些子Partition空间通过位图结构管理。

    这一部分总觉得作者写作太差,读起来非常费劲,第一个NVM页面与第一个子Partition纠缠不清,头结构的存储方式图中看起来是共用一个头结构,文章却说圈起来的头结构都在同一个页面……看了他们的Presentation,才稍微搞清楚一点:每个层级的头结构其实是分开的,一起构成一个大的头,如下图所示
    在这里插入图片描述
    在这里插入图片描述
    用更通俗的语言来说:被划分的Partition会有一个头结构,由于第一个子Partition和这个被划分的Partition的起始地址相同,因此第一个子Partition也有这个相同的头结构,因此也处于被划分的状态,这导致所有第一个子Partition都被划分直到不可划分为止。为了记录不同划分层级的空闲等级,这个头结构需要包含所有划分等级的元数据信息,如上面第一张图所示,L9-L4的信息被存在一个类似数组的地方。这个头结构使用一个4KB的NVM页面存储。此外,文章也没有说明位图到底是如何存储的,通过上面第二张图可以看出,位图似乎是被嵌入到了头结构中。

  • 虚拟地址空间分配:初始化时,ctU会申请1TB的虚拟内存区域(用于提供两个L9 Partition)。这里需要说明的是进程地址空间不会与ctU使用的虚拟地址空间产生冲突,这是Linux Kernel保证的。

  • TLB使用:对于CtFS来说,通过ctK的映射保证能够从虚拟地址访问NVM的物理地址,此时会消耗TLB Entry。因此,相较于其他文件系统,CtFS不会产生更多的TLB使用。分析如下:

    • 非DAX文件系统:文件数据被缓存在内存Buffer中。与CtFS类似,这些缓存Buffer在内存中的数据会占据TLB项,数量取决于访问的数据量;
    • 对于DAX文件系统:NVM的地址空间同样被映射到内核页表中,因此,对NVM的直接访问同样会占据TLB Entry,因此,CtFS也不会占据更多的TLB Entry;

3.3 内核子系统(ctK

这一节作者主要介绍两个部分。其一是Persistent Page Table(PPT),其二是pswap()技术。

PPT与传统的Linux四级页表类似,但PPT被持久化在NVM设备上,且其虚拟地址到物理地址的映射都采用的相对地址。这是因为:① 由于地址空间随机化导致ctU起始虚拟地址不同;② 由于硬件配置不同NVM的起始物理地址可能不同。这里需要说明的是ctK仅有一个PPT,但是每个进程都有一个各自的页表,因此,ctK只能将PPT中的映射关系拷贝到页表中。

pswap()是CtFS提出的一种针对页表的快速交换技术,个人感觉类似SplitFS搞的relink()那一套,不过pswap()的通用性更强,因为他针对持久化页表做出了新的设计。pswap()的功能是原子地交换PPT中两段相同大小的虚拟地址空间。举个例子,页表A指向一段物理地址看空间A,页表B指向物理地址空间B,pswap()后,页表A指向物理地址空间B,页表B指向物理地址空间A。在pswap()过程中,ctK会无效化原来页表A和页表B在进程页表中的映射,并且刷下相应的TLB Entry。因为这样比直接更新映射更高效。pswap()利用Redo Log保证了崩溃一致性,且支持并发操作(只要操作的空间不交叠,否则串行执行。ctK使用二叉搜索树记录将要执行的pswap())。

为了避免pswap()进行过多页表项交换,CtFS定义了swap-aligned,这里不赘述swap-aligned的含义。只需了解拥有swap-aligned性质的页表可以大大减少页表项的交换,如下图所示。这里只需通过修改4个页表项(一个PUD项、一个PMD项以及两个PTE项)即可完成pswap()。图中红蓝项即是被交换的项。其实,完全可以把页表想象成数据索引,pswap()就是对索引进行交换

在这里插入图片描述

作者将由memcpy()实现的pswap()(没有说得太清楚,应该是使用Log直接交换物理空间的数据,造成二次数据拷贝)与ctK使用的pswap()做对比,可以发现pswap()有较大的优势。

在这里插入图片描述

3.4 文件系统操作

由于文件所占用空间是连续的虚拟地址空间,因此文件系统的读操作就变得非常简单,如下图所示,只需要根据offset计算虚拟地址,然后调用memcpy()将数据从NVM上拷贝数据至buf即可。
在这里插入图片描述

对于写操作,CtFS会先为单次写分配一个足够大的Partition,当文件大小增长超过该Partition时,CtFS会升级该Partition。升级的过程实际上就是虚拟地址空间迁移的过程,这时映射的物理数据理应保持不动。这里回顾一下,CtFS支持syncstrict模式,前者不保证数据一致性,后者保证。Partition的升级和数据一致性的保证都需要依赖psawp()进行,下面介绍二者:

  • Partition升级:当某次写入超过当前文件分配的Partition P0时,CtFS会首先分配一个更大的Partition P1,然后调用pswap(P0, P1)完成虚拟地址空间的交换。Partition降级原理和升级类似;

  • 数据一致性:这里主要讨论的是数据覆盖写的情况。CtFS采用一种写后交换策略如下图Step 0所示,要从偏移为O的地方写N个字节,N横跨了三个页面。由此,见Step 1,CtFS分配一个与P0等大的Partition P1,然后拷贝页面p1中未被覆盖的部分,并写入待写的部分。接着,CtFS对虚拟地址空间p1-p3p5-p7做交换,交换完成后,见Step 2,P0对应的数据就是覆盖写之后的数据了。
    在这里插入图片描述

3.5 其他优化

  • 大页优化ctK会尽可能分配大页。这使得L3L3往上的Partition都能够使用大页。然而,如果pswap()需要交换的空间非常小,那么大页就会先被拆解为4KB页面,这额外增加了pswap()的开销。CtFS默认启用大页优化。
  • 追加写优化:在strict模式下,CtFS避免写后交换的操作,而直接追加写数据,然后更新文件大小。
  • 数据I/O优化:作者发现AVX512 NT 512-bit load/store (VMOVDQU和MOVNTDQ)性能最佳。

3.6 文件系统保护

这里需要说明的是,ctU的地址空间被嵌入在进程中,需要防止进程恶意修改文件系统空间。为此,CtFS使用Intel MPK进行用户态防护。即,ctK将所有NVM页面都标记为使用同一个MPK(CtFS称之为NONE)。每当ctU进行文件操作时,ctU将NONE MPK的权限设置为可读写,当完成操作后修改为不可访问。对于不同进程而言,由于MPK在每个核上都有,因此允许某些进程访问CtFS的页面,某些不能,从而起到保护隔离作用。

关于Intel MPK,可以参考[论文分享] Intra-Unikernel Isolation with Intel Memory Protection Keys (mstmoonshine.github.io),核心思想是将内存页面分组并给予权限。

这种保护措施无法避免恶意程序通过修改MPK来破坏文件系统。作者认为这使得CtFS的通用性受限,但可以部署在Data Center场景。

4. 评估(Evaluation)

4.1 微基准测试

4.1.1 追加写

在这里插入图片描述

得益于MMU索引,CtFS在Append负载下大大超过其他文件系统,甚至超过基于Memory-Mapped的SplitFS。这是因为SplitFS还是受制于底层文件系统的索引开销。

4.1.2 其他负载

在这里插入图片描述

可以看到CtFS总是最优的,无论在sync模式下还是在strict模式下

4.1.3 大页优化分析

在这里插入图片描述

这里对CtFS的大页优化进行了对比。实验结果表明大页优化在Append和SWE负载下能够很好地减少Page Fault耗时,因为节省了PPT拷贝开销和页面分配开销(注意,这两个负载面向的都是空文件,而SW、RW、SR、RR面向的都是已经存在的文件,因此没有缺页)。

strict模式的RW下,会触发大量pswap()。相比于使用基本页面,大页优化需要将页面拆分,因此耗时更长。

4.2 真实应用

主要在Level DB和Rocks DB上测试

  • Level DB

在这里插入图片描述

CtFS在Level DB上跑YCSB的结果非常不错。

  • Rocks DB
    在这里插入图片描述

    非常不错。

4.3 资源开销测试

在这里插入图片描述

系统格式化后,CtFS的内存占用十分少。表格表明CtFS的各种操作(open()unlink())时间较少,或许与其目录实现相关,需要研究代码才能清楚。

此外,CtFS在系统格式化后占用空间更少。元数据开销(跑完YCSB LoadA后的空间占用)与EXT4-DAX相似。

4.4 可拓展性

在这里插入图片描述

作者在8核机器上进行测试,测试表明峰值出现在线程数为6的时候。性能下降的原因应该与傲腾NVM的特性相关。OdinFS利用一些异步机制解决了这个问题,有时间可以研读一下:ODINFS: Scaling PM Performance with Opportunistic Delegation | USENIX

5. 总结

本文聚焦于索引开销问题,利用连续虚拟地址空间将索引开销offload至硬件MMU,从而大大减少索引开销。然而,如何分配虚拟地址空间以管理文件仍是一个待解决的挑战(虽然A New Design of In-Memory File System Based on File Virtual Address Framework | IEEE Journals & Magazine | IEEE Xplore好像已经解决了,而且看起来更高效),本文通过类似伙伴分配器的方法高效管理虚拟地址空间,并使用PPT完成页表映射。基于PPT,提出pswap()方法实现一致性操作以及文件大小增减操作。文章从问题、动机到解决方案、挑战到评估测试整套流程工整完整,值得学习。

需要说明的是虽然本文思路简单,然而实现起来并不简单。需要对操作系统内核、进程页表、大页映射等非常熟悉。相比SIMFS而言,该工作更优秀的地方在于其已经开源:robinlee09201/ctFS (github.com)。由于NVM的特性所致,未来NVM的技术发展必定和DRAM、Storage相融合,因此,该工作通过页表来高效访问NVM对于NVM研究者来说具有较高的参考价值。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASP.NET Dotnet 3.5实验室LIMS系统源码

LIMS系统功能包括:检测管理(合同管理、样品管理、样品收发管理、工作任务分配、检测结果登记、复核及审核、留样管理等)、报告管理(报告编制、审核、签发、打印等)、原始记录管理、仪器设备管理、消耗品管理、文件管理…

Oralce系列十九:Oralce的体系结构

Oralce的体系结构 1. 物理结构2. 内存结构2.1 SGA2.2 后台进程 3. 逻辑结构 1. 物理结构 Oracle数据库的物理结构由参数文件、控制文件、数据文件和日志文件组成,用于存储和管理数据库的数据和元数据,每个文件都扮演着不可或缺的角色。 参数文件用于配…

盘点那些VS Code上的常用插件

插件可以使代码开发过程变得更加轻松和高效 文章目录 前言中文版主题插件显示错误游戏插件连接数据库拼写检查插件前端智能提示刷算法题的插件美化注释的插件美化括号的插件自动补全路径和文件名在浏览器中打开 HTML 文件在 VS Code 里面使用 Postman同步 VS Code 配置的插件 前…

MFC第七天 单机版数据库增删改的方法和用户登录(密码修改)、权限管理功能的员工管理系统的应用 以及 CCombox类的属性和方法

文章目录 员工管理系统的应用对TCHAR类型简介:Unicode软件开发中的文字转换方式有三种 CComboBox控件属性和类库介绍CBS_组合框控件属性CComboBox常用方法 员工管理系统示例代码如下Employer_sql.hEmployer_sql.cppMainDlg.hMainDlg.cpp: 实现文件CLoginDlg.hCLogin…

入坑 TS(一)

1、TS 采用类型后置的语法 const str: string "我是字符串"; const num: number "我是数值"; const bool: boolean false;函数怎么写? // 有返回值 function sayHello(str: string): string {return str; } // 无返回值 function sayHello…

Java throws关键字

Java的throws关键字用于声明异常。它向程序员提供了可能发生异常的信息。 因此,最好为程序员提供异常处理代码,以便保持程序的正常流程。 异常处理主要用于处理已检查异常。如果出现任何未检查的异常,例如NullPointerException,则…

jjy-shareV2.0一键分享到微博,QQ空间,QQ好友,微信

介绍 jjy-shareV2.0一键分享到微博,QQ空间,QQ好友,微信 作者:极纪元-橙 作者博客:https://cplvfx.blog.csdn.net/ 码云Gitee:橙cplvfx极纪元 (cplvfx) - Gitee.com 项目地址:jjy-shareV2.…

登录认证(全集)--jwt,Filter,Interceptor详细说明

一、登录校验 问题:在未登录情况下,我们也可以直接访问部门管理、员工管理等功能。由于浏览器与web服务器中的数据交互是通过HTTP协议的,而HTTP协议是无状态的–即每个页面中的请求和响应都是独立的,没有状态存在。所以我们需要进…

WordPress网站的robots文件代码怎样写比较好

本文记载和介绍的是wordpress的robots.txt的在哪儿?以及如何修改robots文件来禁止搜索引擎爬取/ajax目录下的文章。以及如何优化WordPress网站的robots文件 wordpress设置robots文件的目录:/wp-includes/functions.php,然后搜索do_robotstxt…

【雕爷学编程】Arduino动手做(123)---Multi-function扩展板

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…

随机数检测(一)

随机数检测(一)- 随机数自测试概述 1 概述2 产品形态划分和检测项目3 测试方式3.1 概述3.2 单比特频数检测方法3.3块内频数检测方法 1 概述 随机数发生器设计完成后,使用随机数发生器的产品需对其执行测试,防止应用过程中产生不合…

Redis的数据类型及对应的数据结构(二)

接上篇:Redis的数据类型及对应的数据结构(一)_鱼跃鹰飞的博客-CSDN博客 本篇主要讨论剩下的几种数据结构的应用场景 应用场景 集合的主要几个特性,无序、不可重复、支持并交差等操作。 因此 Set 类型比较适合用来数据去重和保…

卧剿,6万字!30个方向130篇!CVPR 2023 最全 AIGC 论文!一口气读完。

一杯奶茶,成为 AIGCCV 视觉前沿弄潮儿! 25个方向!CVPR 2022 GAN论文汇总 35个方向!ICCV 2021 最全GAN论文汇总 超110篇!CVPR 2021 最全GAN论文梳理 超100篇!CVPR 2020 最全GAN论文梳理 在最新的视觉顶会 C…

Java多重捕获块

try块后面可以跟随一个或多个catch块。每个catch块必须包含一个不同的异常处理程序。因此,如果您在不同的异常发生时需要执行不同的任务,请使用Java多重捕获块。 需要记住的要点 一次只会发生一个异常,同时只有一个catch块被执行。 所有的ca…

实训五:数据库安全控制 - MySQL数据库 - 授权与撤销授权

MySQL数据库 - 授权与撤销授权 第1关:数据库授权任务描述相关知识用户管理授权方式 编程要求测试说明参考代码 第2关:数据库撤销权限任务描述相关知识撤销权限 编程要求测试说明参考代码 第1关:数据库授权 任务描述 本关任务:新…

Ubuntu安装Anaconda详细步骤(Ubuntu22.04.1,Anaconda3-2023.03)

本文主要讲述了在Ubuntu中安装anaconda的具体步骤 准备环境:Ubuntu22.04.1,Anaconda3 1.下载Anaconda3 在清华镜像下载Linux版本的anaconda 清华镜像官网Anaconda下载 我选择的是Anaconda3-2023.03-Linux-x86_64.sh 下载好的Anaconda3-2023.03-Linux-…

拦截器Interceptor及与过滤器Filter的区别

统一拦截–拦截器Interceptor 1.概述 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。与过滤器Fil…

【Java|多线程与高并发】设计模式-单例模式(饿汉式,懒汉式和静态内部类)

文章目录 1. 前言2. 单例模式3. 如何保证一个类只有一个实例4. 饿汉式单例模式5. 懒汉式单例模式6. 实现线程安全的懒汉式单例7. 静态内部类实现单例模式8. 总结 1. 前言 设计模式是一种在软件开发中常用的解决复杂问题的方法论。它提供了一套经过验证的解决方案,用…

通信原理概述

通信是指人们通过某种媒介进行信息传递。通过某种介质或通道,将信息从一个地点传递到另一个地点的过程。通信可以是人与人之间的交流,也可以是设备、系统或网络之间的数据传输。 通信信号的分类方法: 1)模拟信号和数字信号(从信号…

数字游戏:如何统计能整除数字的位数?

本篇博客会讲解力扣“2520. 统计能整除数字的位数”的解题思路,这是题目链接。 本题的思路是:取出每一位,判断是否能整除。 如何取出每一位呢?可以采用“mod10除10”的策略。即:每次mod10取出最后一位数,再…