DPDK源码分析之(1)libmbuf模块

DPDK源码分析之(1)libmbuf模块

Author:OnceDay Date:2024年7月2日

漫漫长路,有人对你笑过嘛…

全系列文档可参考专栏:源码分析_Once-Day的博客-CSDN博客

参考文档:

  • DPDK download
  • Getting Started Guide for Linux — documentation (dpdk.org)
  • Sample Applications User Guides — documentation (dpdk.org)
  • 14. Mbuf Library — Data Plane Development Kit 24.07.0-rc1 documentation (dpdk.org)
  • dpdk/lib/mbuf at main · DPDK/dpdk · GitHub
  • TCP/IP Illustrated, Volume 2: The Implementation (kohala.com)

文章目录

      • DPDK源码分析之(1)libmbuf模块
        • 1. 概述
          • 1.1 mbuf介绍
          • 1.2 mbuf设计概念
          • 1.3 mbuf使用mempool
          • 1.4 mbuf对象池构造过程
        • 2. mbuf对象定义
          • 2.1 mbuf数据结构
          • 2.3 mbuf操作函数定义

1. 概述
1.1 mbuf介绍

mbuf(消息缓冲区)库提供了分配和释放缓冲区(mbufs)的功能,这些缓冲区可以被DPDK应用程序用来存储消息。消息缓冲区存储在一个称为mempool(内存池)的结构中,而这个内存池是通过Mempool库来管理的。

通常情况下,rte_mbuf结构体用于承载网络数据包缓冲区,但实际上它可以存储任何类型的数据(例如控制数据、事件等)。为了提高性能,rte_mbuf头部结构被设计得尽可能小,目前只使用了两个缓存行(cache line),并且最常用的字段被放在第一个缓存行中。

  • 内存池(Mempool)管理:内存池库通过预先分配大量固定大小的内存对象(如mbufs),来提高内存分配和释放的效率。这种方法避免了频繁的动态内存分配,从而减少了内存碎片和分配开销。

  • 缓存行优化:缓存行是CPU缓存中存储数据的最小单位。将频繁访问的数据字段放在同一个缓存行中,可以减少CPU缓存未命中(cache miss)的次数,从而提高数据访问速度。

  • 灵活性rte_mbuf不仅能承载网络数据包,还能用于其他用途,如存储控制信息或事件消息。这使得它在各种DPDK应用程序中都能发挥作用。

1.2 mbuf设计概念

为了存储数据包(包括协议头部),考虑了两种方法:

  • 在单个内存缓冲区中嵌入元数据结构,后面跟一个固定大小的区域用于存储数据包。优点是只需要一次操作即可分配/释放整个数据包的内存表示。
  • 使用独立的内存缓冲区分别存储元数据结构和数据包。更灵活,允许元数据结构的分配与数据包缓冲区的分配完全分离。

DPDK选择了第一种方法,元数据包含控制信息,如消息类型、长度、数据起始位置的偏移量以及指向其他mbuf结构的指针,从而实现mbuf链的功能

用于承载网络数据包的消息缓冲区可以处理mbuf链,即需要多个缓冲区来保存完整数据包的情况。例如,巨型帧(jumbo frames)由多个通过next字段链接在一起的mbufs组成。

对于新分配的mbuf,数据的起始位置位于缓冲区开始后RTE_PKTMBUF_HEADROOM字节处,该位置是缓存对齐的。消息缓冲区可以用于在系统的不同实体之间传递控制信息、数据包、事件等。

消息缓冲区还可以使用其缓冲区指针指向其他消息缓冲区的数据部分或其他结构,称为间接mbuf,类似于上面的第二种方法

总结mbuf的设计

  1. 单一内存缓冲区,DPDK选择了在单一内存缓冲区中嵌入元数据结构的设计,简化了分配和释放的操作。
  2. 元数据包含控制信息,元数据结构中包含消息类型、长度、数据起始位置的偏移量以及用于缓冲区链的指针。
  3. 缓冲区链,支持缓冲区链,允许多个mbufs链接在一起,特别适用于需要多个缓冲区来保存完整数据包的情况(如巨型帧)。
  4. 缓存对齐,新分配的mbuf的数据起始位置经过缓存对齐,位于RTE_PKTMBUF_HEADROOM字节之后,优化了性能。
  5. 多用途,消息缓冲区不仅用于传输数据包,还可以在系统中传递控制信息、事件等,具有很高的灵活性。
  6. 完全标准的mbuf操作函数集合,遵循常见标准和原则的mbuf操作函数实现。

下面是单个段组成的mbuf,一个mbuf持有整个报文的数据

在这里插入图片描述

下面是多个段组成的mbuf,一个主mbuf+多个子mbuf共同持有整个报文的数据

在这里插入图片描述

mbuf的构成如下:

| rte_mbuf | ==> rte_mbuf priv size<== | rte_pktmbuf_headroom |     data(Packet data)        | 
|     ==>    struct mbuf     <==       ↓     Headroom(128)    |     dataroom(2176)           |buf.addr    ---->  data_offset|       MBUF_RX_SIZE=2176      |

这是一个带有私有应用数据的mbuf,其默认headroom是128字节,数据空间是2176字节,rte_mbuf是控制元数据,两个cache line共128字节。

1.3 mbuf使用mempool

mbuf缓冲区管理器(Buffer Manager)使用内存池库(Mempool Library)来分配缓冲区。因此,它确保数据包头在不同的通道和内存组(ranks)之间以最佳方式交错排列,以便L3缓存处理。

一个mbuf包含一个字段,用于指示其来源的内存池。当调用rte_pktmbuf_free(m)时,mbuf会返回到其原始的内存池中。

(1) 内存池概述

  • 内存池是一种用于管理固定大小对象集合的高效机制,专门设计用于减少动态内存分配和释放的开销。
  • 在DPDK中,内存池库(Mempool Library)负责管理这些内存池,提供快速的对象分配和释放功能。

(2) 内存池的创建和使用

  • 内存池在初始化时分配一组固定大小的内存块。这些内存块可以被反复使用,以提高性能和减少内存碎片。
  • 应用程序通过调用rte_mempool_create()函数来创建一个新的内存池,并指定每个对象的大小、对象数量以及其他参数。

(3) mbuf和内存池的关系

  • 一个mbuf包含一个字段pool,用于指示该mbuf来源的内存池。
  • 当分配新的mbuf时,实际上是从指定的内存池中取出一个空闲的内存块。
  • 当释放mbuf时,通过调用rte_pktmbuf_free(m)函数,mbuf会被归还到其原始的内存池中,这样可以被再次使用。

(4) 优化性能

  • 内存池的设计考虑了缓存的优化,确保对象分配和释放操作尽可能地缓存友好,从而提高整体性能。
  • 数据包头在不同的内存通道和组之间交错排列,有助于优化L3缓存的处理。

(5) 共享和多用途

  • 内存池可以在多个核心之间共享,支持并行处理。
  • 除了用于网络数据包的存储,内存池还可以用于其他需要高效内存管理的场景,如事件处理和控制信息存储。
1.4 mbuf对象池构造过程

在DPDK中,消息缓冲区(mbuf)的构造过程由API提供的构造函数完成。以下是详细的构造过程:

(1) 内存池的创建,首先,需要创建一个内存池(mempool),用于存储mbuf对象。通过调用rte_mempool_create()函数来创建内存池。在创建内存池时,可以传递一个回调函数,用于初始化每个mbuf对象。

(2) mbuf的初始化,DPDK提供了一个默认的mbuf初始化函数rte_pktmbuf_init()

这个函数在创建内存池时作为回调函数传递给rte_mempool_create(),用于初始化每个mbuf对象。rte_pktmbuf_init()函数会初始化mbuf结构中的一些字段,这些字段一旦设置就不会被用户修改。具体初始化的字段包括:

  • mbuf类型(mbuf type)
  • 来源的内存池(origin pool)
  • 缓冲区的起始地址(buffer start address)
  • 其他一些需要初始化的字段
void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i) {struct rte_mbuf *m = _m;memset(m, 0, mbuf_size);/* start of buffer is after mbuf structure and priv data */m->priv_size = priv_size; //mbuf应用数据空间大小,在私有应用数据之后才是报文数据存储空间m->buf_addr = (char *)m + sizeof(struct rte_mbuf) + priv_size; rte_mbuf_iova_set(m, rte_mempool_virt2iova(m) + mbuf_size);m->buf_len = (uint16_t)buf_len; //mbuf数据空间大小, 包括headroom和tailroom/* keep some headroom between start of buffer and data */m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);/* init some constant fields */m->pool = mp;m->nb_segs = 1;m->port = RTE_MBUF_PORT_INVALID;rte_mbuf_refcnt_set(m, 1);m->next = NULL;
}
2. mbuf对象定义
2.1 mbuf数据结构

相关字段如下:

字段大小描述
cacheline0
buf_addr8 bytes(void *)报文数据的起始地址(虚拟地址)
buf_iova8 bytes(rte_iova_t)报文数据的起始地址(物理地址),总是对齐8字节
rearm_data在RX描述重装时会自动清除接下来8个字节的数据
data_off2 bytes(uint16_t)报文数据的偏移量(相对于buf_addr)
refcnt2 bytes(uint16_t)mbuf引用计数, 用于广播报文零拷贝
nb_segs2 bytes(uint16_t)mbuf的分段sbuf链节点数目,对于一个mbuf不够的报文有效
port2 bytes(uint16_t)报文的输入/输出端口ID(port)
ol_flags8 bytes(uint64_t)网卡硬件卸载特性
rx_descriptor_fields1
packet_type4 bytes(uint32_t)报文数据类型(L2/L3/L4层和隧道信息)
l2_type(4 bits)外层报文的L2类型信息
l3_type(4 bits)外层报文的L3类型信息
l4_type(4 bits)外层报文的L4类型信息
tun_type(4 bits)隧道类型信息
inner_esp_next_proto(8 bit)inner_esp_next_proto(隧道内层信息)
inner_l2_type(4 bit)内层报文的L2类型信息
inner_l3_type(4 bit)内层报文的L3类型信息
inner_l4_type(4 bit)内层报文的L4类型信息
pkt_lenuint32_t(4 byte)整个报文长度(包括所有关联mbuf的数据长度之和)
data_lenuint16_t(2 byte)当前mbuf的报文数据长度(只计算当前mbuf的数据空间)
vlan_tciuint16_t(2 type)(cpu order)VLAN ID,如果RTE_MBUF_F_RX_VLAN存在
hash8 bytes(联合体)报文hash相关信息
rss(4 byte)网卡RSS哈希的结果
fdir(8 byte)网卡FDIR的标识信息 ,包括lo(hash+id) + hi
sched( 8byte)调度队列信息(queue id/traffic class/color)
txadater(8 bytes)dpdk事件设备(eventdev)的关联发送队列(txq)
vlan_tci_outeruint16_t(2 bytes)(cpu order)外层VLAN ID,如果RTE_MBUF_F_RX_QINQ存在
buf_lenuint16_t(2 bytes)当前mbuf的数据空间大小(初始化时给定值)
poolstruct rte_mempool*(8 bytes)当前mbuf所属的内存池
cacheline10 byte
nextstruct rte_mbuf *(8 bytes)长报文的分段mbuf链表,最后一个节点next需要为零
tx_offloaduint64_t (8 bytes)发送网卡硬件卸载信息
l2_lenL2 (MAC) Header Length for non-tunneling pkt。
Outer_L4_len + … + Inner_L2_len for tunneling pkt
l3_lenL3 (IP) Header Length.
l4_lenL4 (TCP/UDP) Header Length.
tso_segszTCP TSO segment size
outer_l3_lenOuter L3 (IP) Hdr Length
outer_l2_lenOuter L2 (MAC) Hdr Length
shinfo12 bytesstruct rte_mbuf_ext_shared_info,mbuf关联的外部数据信息。
priv_sizeuint16_t(2 bytes)mbuf私有数据大小,作为外层应用的mbuf的实际大小来使用。
timesyncuint16_t(2 bytes)Timesync flags for use with IEEE1588
dynfield19 * 4 bytes动态使用字段
2.3 mbuf操作函数定义

相关操作函数和宏定义如下:

操作名称描述
rte_pktmbuf_mtod_offset返回在指定偏移量处的指定类型指针,使用需要注意mbuf数据地址的连续性(是否都在一个mbuf里),即mbuf->buf_addr + mbuf->data_off + offset位置。
rte_pktmbuf_mtod返回偏移量0处指定类型指针,即mbuf->buf_addr + mbuf->data_off位置。
rte_pktmbuf_iova_offset与rte_pktmbuf_mtod_offset类似,但返回的是物理地址(而不是虚拟地址)。
rte_pktmbuf_iova与rte_pktmbuf_mtod类似,但返回的是物理地址(而不是虚拟地址)。
rte_get_rx_ol_flag_name获取Rx offload标识的字符串化表示,一次一个。
rte_get_rx_ol_flag_list获取Rx offload标识的字符串化表示,可以多个标识。
rte_get_tx_ol_flag_name获取Tx offload标识的字符串化表示,一次一个。
rte_get_tx_ol_flag_list获取Rx offload标识的字符串化表示,可以多个标识。
rte_mbuf_prefetch_part1L1缓存预取mbuf第一个cache line的数据
rte_mbuf_prefetch_part2L1缓存预取mbuf第二个cache line的数据
rte_mbuf_iova_get获取mbuf数据的IOVA(虚拟IO地址,IOMMU管理和映射)(mbuf->buf_iova)。
如果RTE_IOVA_IN_MBUF未使能,则等于虚拟地址(mbuf->buf_addr)。
rte_mbuf_iova_set设置IOVA地址,如果RTE_IOVA_IN_MBUF使能,改变mbuf->buf_iova,否则无操作。
rte_mbuf_data_iova获取mbuf报文数据的起始IOVA地址,加上mbuf->data_off。
rte_mbuf_data_iova_default返回默认的mbuf报文数据的起始IOVA地址,固定data offset为RTE_PKTMBUF_HEADROOM(128)
rte_mbuf_from_indirect从一个indirect mbuf的bufffer addr获取其direct(源) mbuf的首地址(指针偏移得到)。
rte_mbuf_buf_addr从mbuf的地址和mempool对象获取mbuf buffer addr
rte_mbuf_data_addr_default从mbuf的地址和mempool对象获取mbuf buffer addr + RTE_PKTMBUF_HEADROOM地址
rte_mbuf_to_baddr获取mbuf buffer addr,从mbuf地址+mempool对象里的mbuf私有数据空间大小算出
rte_mbuf_to_priv返回mbuf私有数据空间的起始地址
rte_pktmbuf_priv_flags返回mbuf私有数据的flags,这是mbuf提供的一种标准私有数据定义。
rte_mbuf_sanity_checkmbuf合规检测,通常用于debug模式,有问题直接panic。
rte_mbuf_checkmbuf合规检测,通常用于debug模式,有问题返回错误原因字符串。
__rte_mbuf_raw_sanity_check原始mbuf合规检测(refcnt=1, next=null, nb_segs=1,通常用于debug模式,有问题直接panic。
rte_mbuf_refcnt_read读取mbuf引用计数,relaxed松散内存序。
rte_mbuf_refcnt_set写入mbuf引用计数,relaxed松散内存序。
__rte_mbuf_refcnt_update更新mbuf引用计数,获取-释放内存序(acquire &release )
rte_mbuf_ext_refcnt_read读取mbuf扩展共享数据的引用计数,relaxed松散内存序。
rte_mbuf_ext_refcnt_set设置mbuf扩展共享数据的引用计数,relaxed松散内存序。
rte_mbuf_ext_refcnt_update更新mbuf扩展共享数据的引用计数,获取-释放内存序(acquire &release )
rte_mbuf_raw_alloc原始方式从mempool申请一个mbuf,buf_addr/buf_iova/buf_len/refcnt=1/nb_segs/next/pool/priv_size等信息应该为重置值。
rte_mbuf_raw_free原始方式释放一个mbuf到mempool,不建议使用,除非优化性能。
rte_pktmbuf_initmempool创建时的初始化函数,用于初始化mbuf全局默认值。
priv_size/buf_addr/buf_iova/buf_len/data_off/pool/nb_segs/port/refcnt/next
其中data_off/nb_segs/port/refcnt/next属于会change的值,需要释放时reset。
rte_pktmbuf_pool_init初始化mempool中私有数据,主要是mbuf的数据空间和私有应用数据空间的大小。
rte_pktmbuf_pool_create创建一个mbuf mempool,提供mbuf数目,私有应用数据和报文数据空间大小等参数。
rte_pktmbuf_pool_create_by_ops与rte_pktmbuf_pool_create类似,但是可以指定mempool ops name。
rte_pktmbuf_pool_create_extbuf与rte_pktmbuf_pool_create类似,但是mbuf的数据存放于外部memory空间。
rte_pktmbuf_data_room_size获取mbuf的数据空间大小(包括RTE_PKTMBUF_HEADROOM)
rte_pktmbuf_priv_size获取mbuf的私有应用数据空间大小,在rte_mbuf和报文数据之间。
rte_pktmbuf_reset_headroom重置mbuf的data_off到默认的headroom起始位置。
rte_pktmbuf_reset重置mbuf的数据,next/pkt_len/tx_offload/vlan_tci/vlan_tci_outer/nb_segs/
port/ol_flags/packet_type/data_off/data_len已初始化。
rte_pktmbuf_alloc从内存池中申请一个mbuf,然后使用rte_pktmbuf_reset进行重置
rte_pktmbuf_alloc_bulk一次从内存池申请多个mbuf,然后使用rte_pktmbuf_reset进行重置
rte_pktmbuf_ext_shinfo_init_helper初始化mbuf的外部共享信息数据结构体,数据需要满足对齐关系。
rte_pktmbuf_attach_extbuf初始化mbuf的外部共享数据,改变buf_addr/buf_iova/buf_len/data_len/data_off=0/ol_flags/shinfo。
修改完成之后,可以调用rte_pktmbuf_reset_headroom/rte_pktmbuf_adj来修复data_len和data_off的值。
rte_pktmbuf_detach_extbufrte_pktmbuf_detach一致。
rte_mbuf_dynfield_copy拷贝rte_mbuf的动态字段dynfield的值。
__rte_pktmbuf_copy_hdr拷贝rte_mbuf的头部数据,port/vlan_tci/vlan_tci_outer/tx_offload/hash/packet_type。
调用rte_mbuf_dynfield_copy拷贝动态空间数据。
rte_pktmbuf_attach将一个mbuf attach到另外一个mbuf上,这种mbuf成为indirect mbuf。
indirect mbuf在attach之前,必须是direct mbuf,其refcnt计数必须为1。
目标mbuf是extbuf,则增加shared info的引用计数,且拷贝ol_flags和shinfo。
目标mbuf是indirect mbuf,增加其源mbuf的引用计数,和普通mbuf一样,拷贝priv_size和ol_flags。
调用**__rte_pktmbuf_copy_hdr**拷贝头部数据。
拷贝data_off/data_len/buf_iova/buf_addr/buf_len/next/pkt_len/nb_segs=1。
__rte_pktmbuf_free_extbuf释放mbuf的extbuf,通过shinfo信息,如果shinfo引用计数为0,则释放extbuf。
__rte_pktmbuf_free_direct减少direct mbuf的引用数目,如果引用计数为0,则直接释放掉direct mbuf。
next/nb_segs=1/refcnt=1, 然后放回mempool
rte_pktmbuf_detach解除一个indirect mbuf的attach状态。
如果mbuf存在extbuf,对于Pinned类型直接Pass。对于其他类型,则调用__rte_pktmbuf_free_extbuf
如果不存在extbuf,直接调用__rte_pktmbuf_free_direct,释放对应的direct mbuf。
重置priv_size,buf_addr,buf_iova,buf_len,data_off,data_len,ol_flags。
__rte_pktmbuf_pinned_extbuf_decrefmbuf释放过程的pinned extbuf处理,重置ol_flags = RTE_MBUF_F_EXTERNAL
如果引用计数为1,则直接结束。如果不为1,则先减去1,最后操作返回值为0的线程再重置为1。
rte_pktmbuf_prefree_seg减少mbuf引用计数,并且判断是否可以free mbuf segment。
mbuf引用计数为1,如果mbuf是indirect mbuf,调用rte_pktmbuf_detach
对于indirect mbuf且存在pinned extbuf,如果extbuf refcnt为1,则需要释放mbuf segment。
mbuf释放操作:next=null,nb_segs=1,返回mbuf(可以回收和释放)。
mbuf引用计数不为1,则减一后为0的线程继续上述释放操作,并且重置mbuf引用计数为1。
rte_pktmbuf_free_seg通过rte_pktmbuf_prefree_seg判读mbuf segment是否可以释放,通过rte_mbuf_raw_free来释放。
rte_pktmbuf_free释放mbuf到mempool池中,支持chain mbuf释放操作。
rte_pktmbuf_free_bulk批量释放mbuf到mempool池中,相当于可以临时缓存mbuf。
rte_pktmbuf_clone基于已有mbuf创建一个clone mbuf,每个mbuf segment都会attach,原mbuf会变成只读mbuf。
rte_pktmbuf_copy基于已有mbuf创建一个全量复制的mbuf,但是private data不会拷贝,两个mbuf将是独立存在的。
可以指定拷贝的报文数据长度,调用**__rte_pktmbuf_copy_hdr**来copy头部。
拷贝会去掉RTE_MBUF_F_INDIRECT和RTE_MBUF_F_EXTERNAL,拷贝后mbuf具有完整的数据。
拷贝mbuf不是逐个mbuf segment拷贝,而是会重新整合数据,尽量填充每个mbuf segment。
rte_pktmbuf_refcnt_update更新mbuf的每个mbuf segment的引用计数。
rte_pktmbuf_headroom获取mbuf的headroom长度,来自data_off。
rte_pktmbuf_tailroom获取mbuf的tailroom长度,来自buf_len - data_off - data_len。
rte_pktmbuf_lastseg获取mbuf的最后一个lastseg。
rte_pktmbuf_pkt_len获取mbuf的报文长度。
rte_pktmbuf_data_len获取mbuf的数据长度。
rte_pktmbuf_prependmbuf报文数据向前扩展指定字节,即尝试减少headroom空间,所以最大上限是headroom大小(data_off=0)。
rte_pktmbuf_append在mbuf后面添加指定字节的数据,尝试减少tailroom,如果空间不足,返回NULL。
rte_pktmbuf_adj移动mbuf的报文数据指针,即data_off,只在第一个mbuf segment移动,不能超过data_len。
rte_pktmbuf_trim裁剪mbuf的尾部数据,裁剪数据长度不能超过最后一个mbuf segment的数据长度(data_len)。
rte_pktmbuf_is_contiguous检查mbuf的数据空间是否连续,即mbuf->nb_segs==1。
__rte_pktmbuf_read在mbuf指定偏移处读取指定长度的数据。
rte_pktmbuf_read如果目标数据是连续的,那么直接返回对应地址的指针,如果非连续,则拷贝到用户buffer中。
rte_pktmbuf_chain将两个mbuf连接起来。
rte_mbuf_tx_offload基于给定的offload参数生成tx_offload值。
rte_validate_tx_offload检查tx_offload的正确性和完整性(ol_flags)。
rte_pktmbuf_linearize将mbuf的数据连续化,要求单个mbuf能放下数据,并且原来的多个mbuf segment被free掉了。
rte_pktmbuf_dump可以dump mbuf的数据。
rte_mbuf_sched_queue_get获取mbuf调度队列的ID。
rte_mbuf_sched_traffic_class_get获取mbuf的traffic class id。
rte_mbuf_sched_color_get获取mbuf的color字段ID。
rte_mbuf_sched_get获取mbuf的queue_id/traffic_class/color的值。
rte_mbuf_sched_queue_set设置mbuf的队列ID。
rte_mbuf_sched_traffic_class_set设置mbuf的class ID。
rte_mbuf_sched_color_set设置mbuf的color ID。
rte_mbuf_sched_set设置mbuf的queue_id, traffic_class and color。

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

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

相关文章

CGAL计算凸包(OSG进行可视化)

目录 一、什么是凸包 二、运行步骤 1、安装依赖项 2、编译osg库 3、运行代码 4、运行截图 一、什么是凸包 凸包是计算几何中的一个基本概念,用来描述一个点集的最小凸包围形。具体来说,给定一个点集,凸包是包含该点集的最小凸多边形或凸多面体。 二维凸包:在二维平面…

算法-常见数据结构设计

文章目录 1. 带有setAll功能的哈希表2. LRU缓存结构3. O(1)时间插入删除随机(去重)4. O(1)时间插入删除随机(不去重)5. 快速获取数据流中的中位数6. 最大频率栈7. 全O(1)结构8. LFU缓存结构 本节的内容比较难, 大多是leetcodeHard难度级别的题目 1. 带有setAll功能的哈希表 哈希…

js计算两个日期直接的间隔天,2018/12/14到2017/11/10有多少天

const startDate new Date(2017-11-10)const endDate new Date(2018-12-14)const diffTime Math.abs(endDate - startDate)const diffDays Math.ceil(diffTime / (1000 * 60 * 60 * 24))console.log(diffDays) // 输出天数差 人工智能学习网站 https://chat.xutongbao.top…

VSCode神仙插件——Codeium (AI编程助手)

1、安装&登录插件 安装过程中会让你登录Codeium账户&#xff0c;可以通过Google账户登录&#xff0c;或者可以注册一个Codeium账户&#xff08;如果没有弹出让你登录账户的界面&#xff0c;可以等安装结束后在右下角找到登录的地方&#xff09; 右下角显示如下图所示&#…

【ubuntu中关于驱动得问题】—— 如何将nouveau驱动程序加入黑名单和安装NVIDIA显卡驱动

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、nouveau驱动程序加入黑名单二、安装NVIDIA显卡驱动总结 前言 NVIDIA显卡驱动是用于支持和优化NVIDIA显卡在计算机系统中运行的关键软件组件。该驱动程序能…

【每日一练】python算数练习题(函数.随机.判断综合运用)

""" 幼儿园加减法练习题 答对点赞表情&#xff0c;答错炸弹表情 表情随机出现 如果全答对有大奖 """ import random df0 #定义答对函数 def dd():global dfdf10bq["&#x1f339;&#x1f339;&#x1f339;","&#x1f389;&…

系统测试-测试方法学习

目录 &#xff08;1&#xff09;等价类 &#xff08;2&#xff09;边界值 &#xff08;3&#xff09;正交&#xff1a;&#xff08;只用于确定排列组合&#xff0c;不确定具体内容&#xff09; (4)判定表法 &#xff08;5&#xff09;流程分析法 &#xff08;6&#xff0…

Django 查询数据

模型参考上一章内容&#xff1a; Django QuerySet对象&#xff0c;filter()方法-CSDN博客 查询数据可以通过以下方法&#xff1a; Book.objects.all() Book.objects.filter() Book.objects.get() 1&#xff0c;添加视图函数 Test/app11/views.py from django.shortcuts im…

昇思25天学习打卡营第12天|MindSpore-基于MobileNetv2的垃圾分类

基于MobileNetv2的垃圾分类 主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入,对图像中的垃圾物体进行检测,并且将检测结果图片保存到文件中。 1、实验目的 了解熟悉垃圾分类应用代码的编写(Python语言);了解Linux操作系统的基本使用;掌握atc命令进行模型…

Spring学习05-[AOP学习-AOP原理和事务]

AOP原理和事务 AOPAOP底层原理比如下面的代码案例手动模拟AOP 动态代理详解JDK动态代理具体实现 AOP AOP底层原理 当实现了AOP,Spring会根据当前的bean创建动态代理(运行时生成一个代理类) 面试题&#xff1a;为什么执行方法的时候&#xff0c;会执行切面里的通知方法&#xf…

华为机试HJ40统计字符

华为机试HJ40统计字符 题目&#xff1a; 想法&#xff1a; 统计上述题目中的四种字符的个数存入字典中&#xff0c;按指定顺序进行输出 input_str input()str_dict {"alpha": 0, "space": 0, "number": 0, "others": 0}for i in …

ZYNQ-LINUX环境C语言利用Curl库实现HTTP通讯

前言 在Zynq-Linux环境中&#xff0c;需要使用C语言来编写APP时&#xff0c;访问HTTP一般可以使用Curl库来实现&#xff0c;但是在Zynq的SDK中&#xff0c;并没有集成该库&#xff0c;在寻找了很多资料后找到了一种使用很方便的额办法。这篇文章主要记录一下移植Curl的过程。 …

【2024_CUMCM】数据预处理、数据分析、数据可视化

目录 2023-c题-问题1 问题分析 偏度 峰度 箱线图 读图 重采样、降采样、升采样 重采样 降采样 升采样 解题代码 2023-c题-问题1 问题分析 问题说白了就是探究品类和销售量这两个数据他们各自内在联系&#xff0c;根据题意&#xff0c;我们先进行数 据预处理&#…

【C语言】 —— 编译和链接

【C语言】 —— 编译和链接 一、编译环境和运行环境二、翻译环境2.1、 预处理2.2、 编译&#xff08;1&#xff09;词法分析&#xff08;2&#xff09;语法分析&#xff08;3&#xff09;语义分析 2.3、 汇编2.4、链接 三、运行环境 一、编译环境和运行环境 平时我们说写 C语言…

C语言中32位浮点数的格式

以 GNU C为例&#xff0c;它遵循 IEEE 754-2008标准中制定的浮点表示规范。在该规范中定义了 5种不同大小的基础二进制浮点格式&#xff0c;包括&#xff1a;16位&#xff0c;32位&#xff0c;64位&#xff0c;128位&#xff0c;256位。其中&#xff0c;32位的格式被用作标准 C…

使用AOP思想实现开闭原则下的流水日志输出

主要实现思想&#xff1a; 通过实现Convert接口来抽取公共组件&#xff0c;获取想要的标准模型。 现在有两个订单场景&#xff0c;一个保存订单&#xff0c;一个为更新订单。构造如下的服务类&#xff1a; import org.springframework.stereotype.Service;Service public clas…

SHAP(SHapley Additive exPlanations)基于XGBoost模型的可解释机器学习

模型可解释性 这是一个关于错误解释机器学习模型的危险以及正确解释它的价值的故事。如果您发现诸如梯度提升机或随机森林之类的集成树模型的鲁棒准确性很有吸引力&#xff0c;但也需要解释它们&#xff0c;那么我希望您发现这些信息有用且有帮助。 试想一下&#xff0c;我们…

julia系列17: tsp问题代码整理

1. 常用库和基础函数 这里是优化版的函数&#xff1a; using TSPLIB,LKH,Distances,PyPlot MaxNum 10000 tspreadTSPLIB(:att48) dist [round.(Int,euclidean(tsp.nodes[i,:],tsp.nodes[j,:])) for i in 1:tsp.dimension,j in 1:tsp.dimension]; pos(tsp::TSP,t::Vector{In…

uniapp跨域问题解决

找到menifest文件&#xff0c;在文件的最后添加如下代码&#xff1a; // h5 解决跨域问题"h5":{"devServer": {"proxy": {"/adminapi": {"target": "https://www.demo.com", // 目标访问网址"changeOrigin…

httpd目录显示乱码问题

vim /etc/httpd/conf/httpd.conf 在<Directory “/var/www/html”>下添加&#xff1a; IndexOptions CharsetUTF-8重启httpd: systemctl restart httpd.service还是不好看&#xff0c;调整下显示宽度&#xff0c;还是这个位置&#xff1a; <Directory “/var/www/ht…