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.pswp.cn/diannao/42524.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42524.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42524.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA中的for-each(增強型for循環)

Java 8及之后的版本中與for-each循環&#xff08;也稱為增強型for循環&#xff09;和數組處理結合使用時&#xff0c;它可能類似于Lambda表達式或流&#xff08;Stream&#xff09;API中的上下文。 舉例&#xff1a; public class ArrLength {public static void main(String…

CGAL計算凸包(OSG進行可視化)

目錄 一、什么是凸包 二、運行步驟 1、安裝依賴項 2、編譯osg庫 3、運行代碼 4、運行截圖 一、什么是凸包 凸包是計算幾何中的一個基本概念,用來描述一個點集的最小凸包圍形。具體來說,給定一個點集,凸包是包含該點集的最小凸多邊形或凸多面體。 二維凸包:在二維平面…

迭代器模式在金融業務中的應用及其框架實現

引言 迭代器模式&#xff08;Iterator Pattern&#xff09;是一種行為設計模式&#xff0c;它提供了一種方法順序訪問一個聚合對象中的各個元素&#xff0c;而又不需要暴露該對象的內部表示。在金融業務中&#xff0c;迭代器模式可以用于遍歷復雜的數據結構&#xff0c;如交易…

算法-常見數據結構設計

文章目錄 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…

解析Java中1000個常用類:DoubleSummaryStatistics類,你學會了嗎?

在線工具站 推薦一個程序員在線工具站:程序員常用工具(http://cxytools.com),有時間戳、JSON格式化、文本對比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。程序員資料站 推薦一個程序員編程資料站:程序員的成長之路(http://cxyroad.com),收錄了一些列的技術教程…

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;&…

(接上一篇)前端弄一個變量實現點擊次數在前端頁面實時更新

實現點擊次數在前端頁面實時更新&#xff0c;確實需要在前端維護一個變量來存儲當前的點擊次數。這個變量通常在Vue組件的data選項中定義&#xff0c;并在組件的生命周期方法或事件處理函數中更新。 以下是實現這一功能的基本步驟&#xff1a; 定義變量&#xff1a;在Vue組件的…

系統測試-測試方法學習

目錄 &#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…

std::deque和std::list的區別是什么

std::deque&#xff08;雙端隊列&#xff09;和std::list&#xff08;雙向鏈表&#xff09;是C標準模板庫&#xff08;STL&#xff09;中兩種不同的序列容器&#xff0c;它們在內部實現、性能特性和使用場景上存在一些關鍵區別。以下是對這些區別的詳細分析&#xff1a; 1. 內…

vue3.0所采用的composition Api與vue2.x使用的Option Api有什么區別

Vue 3.0 引入了 Composition API&#xff0c;與 Vue 2.x 使用的 Options API 相比&#xff0c;有幾個重要的區別和優勢&#xff1a; 代碼組織方式&#xff1a; Options API&#xff08;Vue 2.x&#xff09;&#xff1a; 將相關功能的代碼組織在一個對象中&#xff08;如 data、…

昇思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語言…