性能優化 - 理論篇:CPU、內存、I/O診斷手段

文章目錄

  • Pre
  • 引言
  • 1. CPU 性能瓶頸
    • 1.1 top 命令 —— 多維度 CPU 使用率指標
    • 1.2 負載(load)——任務排隊情況
    • 1.3 vmstat 命令 —— CPU 繁忙與等待
  • 2. 內存性能瓶頸
    • 2.1 操作系統層面的內存分布
    • 2.2 top 命令 —— VIRT / RES / SHR 三個關鍵列
    • 2.3 CPU 緩存與偽共享
    • 2.4 HugePage 技術
    • 2.5 預先加載(AlwaysPreTouch)
  • 3. I/O 性能瓶頸
    • 3.1 硬盤讀寫性能差異
      • “磁盤的速度這么慢,為什么 Kafka 操作磁盤,吞吐量還能那么高?”
    • 3.2 top/vmstat 中的 wa 指標
    • 3.3 iostat 命令 —— 磁盤 I/O 細節指標
    • 3.4 零拷貝原理與實踐
      • 傳統流程(無零拷貝)
      • 零拷貝(以 sendfile 為例)
  • 小結

在這里插入圖片描述


Pre

性能優化 - 理論篇:常見指標及切入點

性能優化 - 理論篇:性能優化的七類技術手段


  1. 引言:木桶理論及短板概念,以及為何關注 CPU、內存、I/O 三大組件。
  2. CPU 性能瓶頸
    2.1 top 命令——多維度 CPU 使用率指標介紹;
    2.2 負載(load)——任務排隊與多核計算機下的正確理解;
    2.3 vmstat 命令——Uninterruptible Sleep、交換分區及上下文切換指標。
  3. 內存性能瓶頸
    3.1 操作系統層面的內存分布(物理內存、虛擬內存、共享內存、邏輯內存、Swap);
    3.2 top 命令——VIRT/RES/SHR 三個關鍵列;
    3.3 CPU 緩存與偽共享——多級緩存結構、Cache line、@sun.misc.Contended;
    3.4 HugePage 技術——TLB、頁表與大頁優勢;
    3.5 預先加載(AlwaysPreTouch)——JVM 堆內存預分配。
  4. I/O 性能瓶頸
    4.1 硬盤讀寫性能差異說明(順序寫 vs 隨機寫與 CPU/內存對比);
    4.2 top/vmstat 中 wa 指標;
    4.3 iostat 命令——%util、avgqu-sz、await、svctm 的含義與閾值;
    4.4 零拷貝原理與實踐——傳統拷貝流程 vs sendfile 零拷貝流程。

引言

在性能優化 - 理論篇:性能優化的七類技術手段 中,我們已經簡要介紹了解決性能問題的常見切入點,如算法優化、緩存策略、并發模型等。但是,在實際運維與性能調優過程中,往往需要首先判斷“系統的短板在哪兒”,才能更有針對性地展開優化工作。正如木桶理論所強調的,整體系統的性能取決于最薄弱的那一塊。當 CPU、內存、I/O 這三大計算機資源之間存在速度差異時,就會產生性能瓶頸,拖累整個系統。

目標:

  1. 哪些系統組件容易成為性能瓶頸;
  2. 如何通過常用命令和指標判斷它們是否真的已經成為瓶頸。

我們接下來將以 Linux 下常見的 top、vmstat、iostat 等工具為切入口,分別從 CPU、內存和 I/O 三個維度進行,快速鎖定系統可疑短板,為后續深入分析提供方向。


1. CPU 性能瓶頸

CPU(中央處理器)是系統中最核心的計算單元,當 CPU 無法及時處理任務時,就會導致其他任務排隊等待,進而產生明顯的性能問題。下面介紹三種常用命令和思路,用于判斷 CPU 是否出現瓶頸。

1.1 top 命令 —— 多維度 CPU 使用率指標

啟動 top(或 htop)后,可以按下數字鍵 1 來查看每個邏輯核心的使用情況。

在這里插入圖片描述

典型輸出中,我們重點關注以下幾列指標:

  • us(user):用戶態占用的 CPU 百分比,即由普通應用程序耗費的 CPU 時間;
  • sy(system):內核態占用的 CPU 百分比,用于判斷系統調用、驅動中斷等是否頻繁;
  • ni(nice):修改過優先級的進程占用的 CPU 百分比,通常比較少見;
  • wa(iowait):CPU 因等待 I/O 完成而空閑的時間百分比,當該值過高時,往往意味著 I/O 子系統可能成為瓶頸
  • hi(hardware interrupts):硬中斷所占用的 CPU 百分比,用來評估中斷處理對系統的開銷;
  • si(soft interrupts):軟中斷所占用的 CPU 百分比;
  • st(steal time)在虛擬化環境中,虛擬機因等待宿主機 CPU 而被“偷取”的時間百分比,常出現在超賣(overcommit)嚴重的云服務器上;
  • id(idle):空閑 CPU 百分比,即未被任何用戶態或內核態程序占用的時間。

關注要點:通常,當 id(空閑)低于 10% 時,就有必要進一步分析。

  • 如果 us ? sy,說明大多數開銷來自應用程序本身的計算;
  • 如果 sy 較高,且伴隨 cs(上下文切換)急劇上升,則可能是鎖競爭或系統調用過于頻繁;
  • 如果 wa 持續超過 10%以上,需重點檢查磁盤或網絡 I/O。

1.2 負載(load)——任務排隊情況

除了 topuptimecat /proc/loadavg 也能查看系統負載(load average),通常顯示最近 1 分鐘、5 分鐘、15 分鐘的平均值。Load 本質上表示系統可運行隊列(包括正在運行與可運行狀態)的長度。

  • 單核 CPU

    • Load < 1:CPU 有閑置;
    • Load ≈ 1:CPU 滿負載;
    • Load > 1:存在任務排隊,開始出現瓶頸。
      在這里插入圖片描述
  • 多核 CPU
    我們需要把 Load 與 CPU 核心數進行對比,比如一臺 8 核機器,如果 Load ≈ 8,表明所有核心基本都在滿負載;如果 Load ≈ 16,則代表有 8 個任務在排隊等待。

正確理解

  • 若某時刻 Load = 10,而你使用的是一臺 16 核服務器,說明系統還有剩余計算能力(仍可并行處理多達 6 個任務)。
  • 若 Load ≈ CPU 核心數 × 1.2 時,已有一定排隊壓力;若 Load ≈ CPU 核心數 × 1.5 或更高,則問題嚴重。

通過 Load 我們能夠大致判斷“CPU 是否不堪重負”,但無法區分是 CPU 本身飽和,還是等待 I/O 導致的大量進程處于可運行隊列。


1.3 vmstat 命令 —— CPU 繁忙與等待

在這里插入圖片描述

vmstat 2(每 2 秒刷新一次)能輸出更細粒度的系統指標,其中幾列指標與 CPU 相關:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----r  b   swpd   free   buff  cache    si   so    bi    bo   in   cs us sy id wa st2  1      0  10240  40844 124536     0    0     3    12  185  210 30  5  60  5  0
  • b(blocked)處于“不可中斷睡眠(D 狀態)”的進程數,通常是因 I/O 等待。如果 b 值持續大于 0,表明存在 I/O 隊列或其他資源等待,可能是 I/O 瓶頸。它的意思是等待 I/O,可能是讀盤或者寫盤動作比較多.
  • si(swap in)/ so(swap out)每秒發生的換入換出頁數;如果這兩列不為 0,說明系統正在頻繁地使用 Swap,這會嚴重影響性能,應盡快檢查內存壓力。
  • cs(context switches)每秒發生的上下文切換次數;當 cs 過高,且同時伴隨 sy 較高時,說明進程/線程切換開銷大,可能是線程數過多或鎖競爭激烈。
  • us/sy/id/wa:與 top 中類似,判斷用戶/內核占用、空閑與 I/O 等待情況。

綜合判斷

  • b 持續上升、wa 較高時,初步判斷可能是 I/O 瓶頸,需要結合 iostat 等工具深入排查;
  • si/so 不為 0,說明系統在用 Swap 分區,需檢查內存是否不足;
  • cs 過高且 sy 上升,需分析是否存在鎖競爭或短生命周期進程過多。

此外,可以通過查看單個進程的上下文切換次數來判斷某個進程是否“頻繁切換”,例如:

cat /proc/<PID>/status | grep ctxt_switches
voluntary_ctxt_switches:    93950
nonvoluntary_ctxt_switches: 171204
  • voluntary_ctxt_switches:該進程主動自愿讓出 CPU(如等待某個事件完成);
  • nonvoluntary_ctxt_switches:該進程被操作系統搶占而發生的上下文切換次數。

如果某進程這兩個值都非常高,說明它在不斷被搶占或頻繁等待,可能是線程數過多或鎖等待。


2. 內存性能瓶頸

內存層面容易出現的問題,主要分為“物理內存不足導x致 Swap 大量使用”與“CPU 緩存相關的并發偽共享”兩種大類。下面我們逐項介紹如何通過系統工具進行排查。

在這里插入圖片描述

2.1 操作系統層面的內存分布

  • 物理內存(RAM):實際安裝在主板上的內存條容量,例如 4GB、8GB 等。
  • 虛擬內存(Swap):將磁盤劃分一部分用作內存,當物理內存不足時,操作系統會將部分冷數據遷移到 Swap 以騰出空間。虛擬內存容量 = 物理內存 + Swap 分區。
  • 共享內存(Shared Memo ry):多個進程可以映射同一段物理內存,用于進程間高速通信。例如,/dev/shm、某些動態鏈接庫(.so 文件)加載到內存后可被多個進程復用。
  • 邏輯內存(Virtual Address):每個進程看到的“線性地址空間”,操作系統通過頁表將其映射到實際的物理內存或 Swap。這也是為什么你在程序中看到的指針地址并非物理地址的原因。

注意:當物理內存 + Swap 均被占滿時,新的內存請求會導致 OOM(OutOfMemory)或進程被殺死。

2.2 top 命令 —— VIRT / RES / SHR 三個關鍵列

在這里插入圖片描述

top 中查看進程時,內存相關列通常有:

  • VIRT(Virtual Memory Size):進程使用的虛擬內存大小,包括代碼段、庫、堆、棧以及已映射但未實際占用物理內存的區域。通常很大,但并不代表真正占用物理內存。
  • RES(Resident Memory Size)進程當前實際占用的物理內存大小,也是最需要關注的數值。如果某個 Java 進程的 RES 一直飆高,說明物理內存壓力較大。
  • SHR(Shared Memory Size):進程占用的可被其他進程共享的內存大小,例如共享庫部分。如果多進程復用同一 .so 文件,這部分會重復顯示在各個進程的 SHR 中。

監控要點

  • 持續監測關鍵服務(如 JVM 進程、數據庫進程)的 RES 值。
  • 若系統物理內存使用已接近 phy_total – (buffer + cache),并且 Swap 使用量不斷增長,則要警惕可能發生的內存抖動與性能下降。

2.3 CPU 緩存與偽共享

在這里插入圖片描述

CPU 與主內存(DRAM)之間的速度差通常超過百倍,因而多級緩存(L1、L2、L3)成為不可或缺的高速存儲層次:

  • L1 Cache:通常 32KB 左右(分為數據緩存與指令緩存),訪問延遲約 4 ~ 5 周期;
  • L2 Cache:通常 256KB ~ 512KB,訪問延遲約 12 ~ 15 周期;
  • L3 Cache(若存在):幾 MB 級別,延遲約 30 ~ 40 周期;

偽共享(False Sharing) 是并發編程中常見的性能陷阱:

  • 當多個線程頻繁修改位于同一個 Cache line(通常 64 字節)內的不同變量時,每次寫操作會導致該整行緩存失效,并在其他 CPU 核之間反復淘汰與重載,極大增加內存系統開銷
  • 舉例:假設兩個線程分別修改位于同一 64 字節 Cache line 內的 ab 兩個變量。線程 A 寫 a 時,整個 Cache line 被標記為 Modified,線程 B 如果此后寫 b,則需要從主內存或其他 CPU 的緩存中重新加載該 Cache line,才可再寫;如此反復執行,會導致大量緩存一致性流量,嚴重拖慢性能。

要獲得 Cache line 大小,可以執行:

在這里插入圖片描述

cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size
cat /sys/devices/system/cpu/cpu0/cache/index2/coherency_line_size
cat /sys/devices/system/cpu/cpu0/cache/index3/coherency_line_sizecat /proc/cpuinfo | grep cache_alignment

通常返回 64 表示 64 字節的 Cache line 大小。

在 Java 8+ 中,可以通過在類字段上添加 @sun.misc.Contended 注解(并在啟動參數中加上 -XX:-RestrictContended)來避免某些字段被放在同一 Cache line 中,從而緩解偽共享。但要謹慎使用,因為開啟 @Contended 會導致對象頭占用增加。更常見的做法是:

  • 手動在頻繁并發寫的變量之間插入“填充字段”(padding),確保它們位于不同 Cache 行;
  • 盡可能使用無鎖/弱同步的數據結構,如 LongAdderConcurrentHashMap 等,減少多個線程對同一變量的寫沖突。

2.4 HugePage 技術

在這里插入圖片描述

當系統物理內存較大時,傳統 4KB 大小的頁表(Page)在 TLB(Translation Lookaside Buffer)中能映射的頁數量有限,頻繁發生 TLB miss 會帶來高昂的頁表查找開銷。HugePage(大頁)通過將單頁大小從 4KB 改為 2MB(或甚至 1GB,在某些架構上),可以顯著減少頁表條目數量與 TLB miss 的幾率。

  • TLB:CPU 內部的一個小型緩存,用來保存最近訪問的虛擬地址與物理地址映射,當訪問的頁不在 TLB 中時,會發生 TLB miss,引發多次內存訪問以查找頁表。

  • 使用 HugePage 的好處

    1. 減少頁表條目數量,從而提升 TLB 命中率;
    2. 減少內核在處理 TLB 缺失時的訪問開銷;
    3. 對于大內存數據庫、高并發 Java 堆環境(如需要分配 幾十 GB 堆),HugePage 能帶來更穩定的訪問延遲。
  • 配置方式(Linux 示例)

    1. 編輯 /etc/sysctl.conf,例如:

      vm.nr_hugepages = 1024   # 預留 1024 個 2MB 大頁(約 2GB)
      
    2. 重新加載:sysctl -p,并在 JVM 啟動時添加 -XX:+UseLargePages-XX:UseTransparentHugePages(內核支持自動管理)。

  • 注意:HugePage 在申請時需要連續物理內存,如果系統已經運行很久并且內存較為分散,可能會申請失敗;常見做法是在系統啟動時一并保留大頁。

2.5 預先加載(AlwaysPreTouch)

默認情況下,JVM 在啟動過程中會根據 -Xms(初始堆)和 -Xmx(最大堆)設置為堆預留地址空間,但實際物理內存分配僅在真正訪問某個頁面時才發生(所謂“按需分配”)。

  • 添加參數 -XX:+AlwaysPreTouch 后,JVM 會在啟動時預先觸碰(touch)堆內存中的所有頁面,使操作系統一次性分配所有物理頁面。

  • 優點

    1. 在后續運行時能保證頁面映射已經就緒,減少首次訪問時因頁面分配帶來的延遲;
    2. 對于實時性要求較高的服務,可以避免運行過程中出現大規模“頁面分配阻塞”。
  • 缺點:啟動時間會明顯變長,尤其是堆較大時需觸摸的頁更多;而且如果常駐內存要占用大量物理頁,系統需要保證提前就有足夠空閑內存。


3. I/O 性能瓶頸

在這里插入圖片描述

I/O 子系統通常是整臺機器中最慢的部分,因此一旦 I/O 無法跟上 CPU 和內存的處理速度,就會導致 iowait 升高、響應延遲拉長。下面介紹如何使用常用工具判斷與排查 I/O 瓶頸。

3.1 硬盤讀寫性能差異

首先,了解不同存儲介質的讀寫特性:

  • 機械硬盤(HDD):順序讀寫性能較好(幾十 MB/s 到上百 MB/s),但隨機讀寫性能極差(可能只有幾 MB/s)。
  • SSD(固態硬盤):順序讀寫與隨機讀寫性能都較高,但相對機械盤而言,順序寫入略遜一籌;而隨機小文件 I/O 性能可達數十萬 IOPS。
  • 內存(RAM):讀寫帶寬可達數十 GB/s,延遲僅幾十納秒。

由于 CPU 與內存之間的速度差已經很大(百倍以上),因此存儲層與內存層之間的速度差則更為懸殊:

CPU 緩存(L1):幾十 GB/s,延遲 ~4 周期  
內存(DRAM):幾十 GB/s,延遲 ~100 納秒  
SSD 順序寫:500 MB/s ~ 1 GB/s,延遲數十 微秒  
SSD 隨機寫:1 ~ 10 MB/s (取決于塊大小),延遲 ~100 微秒 ~ 1 毫秒  
機械盤隨機寫:1 ~ 5 MB/s,延遲 >1 毫秒  

因此,在某些高并發場景下,尤其要盡量減少隨機 I/O、避免小文件頻繁讀寫。

“磁盤的速度這么慢,為什么 Kafka 操作磁盤,吞吐量還能那么高?”

磁盤之所以“慢”,主要瓶頸在“尋道”(seek time)操作上。根據 Kafka 官方測試,機械硬盤的尋道時長平均可達到 10ms 左右。與此同時,磁盤對順序寫入與隨機寫入的性能差距極大——順序寫的吞吐往往是隨機寫的數千倍。Kafka 恰好將寫日志(append log)設計為順序寫

  • 每條消息追加到分區對應的日志文件末尾,磁頭僅需在當前寫入位置連續移動,不要頻繁跳轉;
  • 借助操作系統頁緩存(PageCache)和批量刷盤(batch flush)策略,將多條消息合并為一次大塊寫入,進一步降低尋道帶來的延遲;
  • 通過零拷貝(sendfile)技術,將磁盤頁緩存直接傳輸給網絡套接字,減少內核與用戶空間之間的內存拷貝。

因此,雖然機械磁盤的“隨機寫”極慢,但 Kafka 最大化地利用了“順序寫”的高吞吐特性,進而在每秒百萬級消息寫入場景下依然能夠保持很高的磁盤利用率與整體吞吐。


3.2 top/vmstat 中的 wa 指標

在這里插入圖片描述

top 中,wa(iowait)列顯示 CPU 因等待 I/O 完成而空閑的百分比;在 vmstat 輸出中同樣會顯示 wa

  • 如果 wa 持續超過 10%,意味著有大量進程在等待 I/O 完成,此時系統整體吞吐將明顯下降。
  • b(Uninterruptible Sleep) 大于 0 時,也表明某些進程在等待 I/O。

案例:某 Web 服務在高并發下突然響應變慢,top 發現 id 幾乎為 0,wa 常駐 20% 左右,說明大量請求在等待磁盤寫日志或數據庫 IO,可結合 iostat 查明是日志盤還是數據庫盤出現瓶頸。

3.3 iostat 命令 —— 磁盤 I/O 細節指標

在這里插入圖片描述

iostat -x 2(每 2 秒刷新一次擴展統計)能夠展示各塊設備(Device)的詳細 I/O 性能指標,例如:

Device:         rrqm/s wrqm/s   r/s   w/s  rMB/s wMB/s avgrq-sz avgqu-sz  await  r_await w_await  svctm  %util
sda               0.00   20.00  0.50 10.00   0.02   0.80    160.00     5.20  30.40   10.20   35.80   2.80 28.00
sdb               0.00    0.00  0.00  0.10   0.00   0.01     80.00     0.02  20.00    0.00   20.00   2.00  0.20

重點關注以下幾列:

  • %util設備利用率,表示磁盤忙碌時間占比。一般當 %util 超過 80% 時,就說明該塊設備壓力過大。
  • avgqu-sz(Average Queue Size):平均請求隊列長度,類似“路口排隊汽車數”。數值越小越好;若大于 5 左右,就要警惕排隊嚴重。
  • await(Average Wait Time):平均請求等待時長(ms),包括排隊時間與服務時間,經驗上若 await > 5 ms,就說明磁盤響應變慢;若 await > 10 ms,說明磁盤 I/O 瓶頸明顯。
  • svctm(Service Time):平均服務時間(ms),只包含處理時間(不含排隊)。當 awaitsvctm 差距很大時,說明排隊時間占比大;當兩者接近時,說明磁盤本身速度接近瓶頸。

閾值參考

  • %util > 80%:磁盤帶寬已接近極限;
  • avgqu-sz > 5 :隊列較長,建議分散 I/O 或擴容;
  • await > 10 ms:I/O 響應明顯變慢。

3.4 零拷貝原理與實踐

在傳統的數據從磁盤寫入網絡的流程中,需要 CPU 較多參與:

  1. read():將磁盤數據從內核空間拷貝到用戶空間;
  2. write():將用戶空間的數據再次拷貝回內核空間的網絡緩沖區;
  3. 網絡發送:內核將網絡緩沖區數據通過網卡發出。

中間的兩次拷貝(磁盤→內核→用戶、用戶→內核→網卡)都要經過內存拷貝,且需要在用戶態與內核態之間頻繁切換,增加了 CPU 與內存總線負擔。

傳統流程(無零拷貝)

在這里插入圖片描述

磁盤 → [內核頁緩存] → <拷貝> → [用戶緩沖區] → <拷貝> → [網絡緩沖區] → 網絡發送

零拷貝(以 sendfile 為例)

在這里插入圖片描述

磁盤 → [內核頁緩存] ——sendfile——> [網絡緩沖區] → 網絡發送
  • 減少一次內存拷貝:sendfile 系統調用讓內核直接將頁緩存映射到網絡緩沖區,省去磁盤→用戶空間→內核網絡緩存的拷貝。
  • 減少用戶態/內核態切換:應用直接調用 sendfile(fd_in, fd_out, ...),內核內部完成整條鏈路數據流動,無需在中間將數據暴露到用戶空間。

應用場景

  • Kafka:批量順序寫入磁盤并直接 sendfile 將日志 segment 切片零拷貝到 socket;
  • Nginx:靜態文件服務時,使用 sendfile 減少 CPU 拷貝開銷;
  • Netty:在 Linux 平臺可結合 FileRegionsendfile 實現高效大文件傳輸。

并非所有場景都適合零拷貝:

  • 如果需要對文件內容做二次加工(如壓縮、加密、轉換等),就無法直接用 sendfile;
  • 若數據源并非文件而是來自內存生成的動態內容,則零拷貝價值有限。

小結

重點從“計算機資源短板”角度,闡述了 CPU、內存與 I/O 三大組件易成瓶頸的典型特征,以及如何通過 Linux 工具進行初步診斷:

  1. CPU

    • top 查看 us、sy、ni、wa、hi、si、st、id 等多維度指標;
    • load average 結合 CPU 核心數評估任務排隊情況;
    • vmstat 查看 bsi/socs 等指標,判斷 I/O 等待與上下文切換開銷。
  2. 內存

    • 理解物理內存、虛擬內存(Swap)、共享內存與邏輯內存的關系;
    • 關注 top 中的 VIRT/RES/SHR,重點監控進程實際占用物理內存(RES)與 Swap 使用情況;
    • 理解多級 CPU 緩存架構及偽共享帶來的慘重開銷,學會使用 @Contended 或手動填充(Padding)緩解問題;
    • 掌握 HugePage 技術以減少 TLB miss 開銷,了解 JVM -XX:+AlwaysPreTouch 預先加載對啟動與運行性能的影響。
  3. I/O

    • 認識機械盤、SSD、內存之間的性能差異;
    • topvmstat 中關注 wab,結合 iostat%utilavgqu-szawaitsvctm 指標判斷磁盤負載與響應狀況;
    • 理解零拷貝原理,掌握何時通過 sendfile 等機制減少內核與用戶空間拷貝,以提升大數據量傳輸效率。

這些方法只能幫助我們對 CPU、內存與 I/O 的基本瓶頸進行“定性判定”,但要精準到“真正的問題根源”——例如,哪個具體線程在搶占 CPU?哪個函數導致頻繁上下文切換?哪個文件或邏輯請求引起高磁盤 I/O?——還需要依賴更深入的性能分析工具(如 perf、eBPF、JVM Flight Recorder、系統追蹤工具等)收集更細粒度的數據。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82404.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82404.shtml

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

相關文章

GPIO的內部結構與功能解析

一、GPIO總體結構 總體構成 1.APB2(外設總線) APB2總線是微控制器內部連接CPU與外設&#xff08;如GPIO&#xff09;的總線&#xff0c;負責CPU對GPIO寄存器的讀寫訪問&#xff0c;支持低速外設通信 2.寄存器 控制GPIO的配置&#xff08;輸入/輸出模式、上拉/下拉等&#x…

汽車總線分析總結(CAN、LIN、FlexRay、MOST、車載以太網)

目錄 一、汽車總線技術概述 二、主流汽車總線技術對比分析 1. CAN總線&#xff08;Controller Area Network&#xff09; 2. LIN總線&#xff08;Local Interconnect Network&#xff09; 3. FlexRay總線 4. MOST總線&#xff08;Media Oriented Systems Transport&#x…

WordPress 6.5版本帶來的新功能

WordPress 6.5正式上線了&#xff01;WordPress團隊再一次為我們帶來了許多新的改進。在全球開發者的共同努力下&#xff0c;WordPress推出了許多新的功能&#xff0c;本文將對其進行詳細總結。 Hostease的虛擬主機現已支持一鍵安裝最新版本的WordPress。對于想要體驗WordPres…

【vue+ts】找不到模塊“./App.vue”或其相應的類型聲明

報錯&#xff1a;找不到模塊“./App.vue”或其相應的類型聲明。 原因&#xff1a;typescript只能理解.ts文件&#xff0c;無法理解.vue文件。 解決&#xff1a;在src/env.d.ts下添加&#xff1a; /// <reference types"vite/client" /> // 三斜線引用告訴編譯…

Nginx+Tomcat 負載均衡群集

目錄 一&#xff0c;部署Tomcat 1&#xff0c;案例概述 2&#xff0c;案例前置知識點 &#xff08;1&#xff09;Tomcat簡介 &#xff08;2&#xff09;應用場景 3&#xff0c;案例實施 3.1&#xff0c;實施準備 &#xff08;1&#xff09;關閉firewalld防火墻 &#…

Spring Boot Actuator未授權訪問漏洞修復

方案1&#xff1a;在網關的配置文件里增加以下配置 management:endpoints:web:exposure:include: []enabled-by-default: falseendpoint:health:show-details: ALWAYS 方案二&#xff1a;直接在nginx配置攔截actuator相關接口 location /actuator { return 403; …

動態規劃之網格圖模型(二)

文章目錄 動態規劃之網格圖模型&#xff08;二&#xff09;LeetCode 931. 下降路徑最小和思路Golang 代碼 LeetCode 2684. 矩陣中移動的最大次數思路Golang 代碼 LeetCode 2304. 網格中的最小路徑代價思路Golang 代碼 LeetCode 1289. 下降路徑最小和 II思路Golang 代碼 LeetCod…

React 編譯器

&#x1f916; 作者簡介&#xff1a;水煮白菜王&#xff0c;一位前端勸退師 &#x1f47b; &#x1f440; 文章專欄&#xff1a; 前端專欄 &#xff0c;記錄一下平時在博客寫作中&#xff0c;總結出的一些開發技巧和知識歸納總結?。 感謝支持&#x1f495;&#x1f495;&#…

mac下通過anaconda安裝Python

本次分享mac下通過anaconda安裝Python、Jupyter Notebook、R。 anaconda安裝 點擊&#x1f449;https://www.anaconda.com/download&#xff0c; 點擊Mac系統安裝包&#xff0c; 選擇Mac芯片&#xff1a;蘋果芯片 or intel芯片&#xff0c; 選擇蘋果芯片圖形界面安裝&#x…

Pandas 技術解析:從數據結構到應用場景的深度探索

序 我最早用Python做大數據項目時&#xff0c;接觸最早的就是Pandas了。覺得對于IT技術人員而言&#xff0c;它是可以屬于多場景的存在&#xff0c;因為它的本身就是數據驅動的技術生態中&#xff0c;對于軟件工程師而言&#xff0c;它是快速構建數據處理管道的基石&#xff1…

【循環神經網絡RNN第一期】循環神經網絡RNN原理概述

目錄 &#x1f9e0; 什么是循環神經網絡&#xff08;RNN&#xff09;&#xff1f;&#x1f501; RNN 的結構圖&#x1f504; RNN 的“記憶”與問題RNN梯度推導 &#x1f9ec; LSTM&#xff1a;解決長期依賴問題&#x1f9f1; LSTM 的核心結構LSTM總結 參考 人類在思考的時候&am…

代碼隨想錄算法訓練營 Day60 圖論Ⅹ Bellmen_ford 系列算法

圖論 題目 94. 城市間貨物運輸 I Bellmen_ford 隊列優化算法 SPFA 大家可以發現 Bellman_ford 算法每次松弛 都是對所有邊進行松弛。 但真正有效的松弛&#xff0c;是基于已經計算過的節點在做的松弛。 本圖中&#xff0c;對所有邊進行松弛&#xff0c;真正有效的松弛&#…

Juce實現Table自定義

Juce實現Table自定義 一.總體展示概及概述 在項目中Juce中TableList往往無法滿足用戶需求&#xff0c;頭部和背景及背景顏色設置以及在Cell中添加自定義按鈕&#xff0c;所以需要自己實現自定義TabelList&#xff0c;該示例是展示實現自定義TableList&#xff0c;實現自定義標…

C++ set數據插入、set數據查找、set數據刪除、set數據統計、set排序規則、代碼練習1、2

set數據插入&#xff0c;代碼見下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…

深度學習賦能圖像識別:技術、應用與展望

論文&#xff1a; 一、引言? 1.1 研究背景與意義? 在當今數字化時代&#xff0c;圖像作為信息的重要載體&#xff0c;廣泛存在于各個領域。圖像識別技術旨在讓計算機理解和識別圖像內容&#xff0c;將圖像中的對象、場景、行為等信息轉化為計算機能夠處理的符號或數據 &am…

深入解析C++引用:從別名機制到函數特性實踐

1.C引用 1.1引用的概念和定義 引用不是新定義?個變量&#xff0c;而是給已存在變量取了?個別名&#xff0c;編譯器不會為引用變量開辟內存空間&#xff0c;它和它引用的變量共用同?塊內存空間。比如四大名著中林沖&#xff0c;他有一個外號叫豹子頭&#xff0c;類比到C里就…

【從0-1的HTML】第1篇:HTML簡介

1 HTML簡介 HTML是用來描述網頁的一種語言,是超文本標記語言的縮寫(Hyper Text Markup Language),不屬于編程語言的范疇&#xff0c;屬于一種標記語言。 標記語言使用一套標記標簽(Markup tag)&#xff0c;又稱為標簽,HTML就是使用標記標簽來描述網頁。 1.2 HTML標簽 1、HTM…

vue+cesium示例:地形開挖(附源碼下載)

基于cesium和vue繪制多邊形實現地形開挖效果&#xff0c;適合學習Cesium與前端框架結合開發3D可視化項目。 demo源碼運行環境以及配置 運行環境&#xff1a;依賴Node安裝環境&#xff0c;demo本地Node版本:推薦v18。 運行工具&#xff1a;vscode或者其他工具。 配置方式&#x…

qwen大模型在進行詞嵌入向量時,針對的詞表中的唯一數字還是其他的?

qwen大模型在進行詞嵌入向量時,針對的詞表中的唯一數字還是其他的? Qwen大模型進行詞嵌入向量時,針對的是詞表中每個 Token 對應的唯一數字(Token ID) ,核心邏輯結合詞表構建、嵌入過程展開 一、Qwen 詞表與 Token ID Qwen 用 BPE 分詞器(基于 tiktoken,以 cl100k 為…

動態規劃-1143.最長公共子序列-力扣(LeetCode)

一、題目解析 對于給定了兩個字符串中&#xff0c;需要找到最長的公共子序列&#xff0c;也就是兩個字符串所共同擁有的子序列。 二、算法原理 1、狀態表示 dp[i][j]&#xff1a;表示s1的[0,i]和s2的[0,j]區間內所有子序列&#xff0c;最長子序列的長度 2、狀態轉移方程 根…