標記-清除算法中的可達性判定與Chrome DevTools內存分析實踐

引言

在現代前端開發中,內存管理是保證應用性能與用戶體驗的核心技術之一。作為JavaScript運行時的基礎機制,標記-清除算法(Mark-and-Sweep) 通過可達性判定決定哪些內存需要回收,而Chrome DevTools提供的Memory工具則為開發者提供了深度的內存分析能力。本文將深入剖析垃圾回收機制的核心原理,并結合Chrome DevTools實踐,展示如何進行高效的內存泄漏檢測與優化。

通過本文,您將學習到:

  • 標記-清除算法中可達性判定的工作原理與實現機制
  • Chrome DevTools Memory工具的核心功能與使用技巧
  • 如何使用堆快照(Heap Snapshot)檢測內存泄漏
  • 循環引用、DOM引用等常見內存問題的解決方案
  • 內存分析的進階技巧與優化最佳實踐
  • 構建完整的內存監控與優化工作流

本文將結合代碼示例、可視化圖表與實戰案例,幫助您建立完整的JavaScript內存管理知識體系,提升應用性能與穩定性。

一、標記-清除算法中的可達性判定

1. 可達性分析基本原理

在JavaScript運行時環境中,標記-清除算法(Mark-and-Sweep)是最基礎的垃圾回收機制。其核心思想是通過可達性分析(Reachability Analysis)判定對象是否存活。算法從一組稱為"GC Roots"的根對象出發,遍歷整個對象引用圖(Object Reference Graph),所有能被訪問到的對象被標記為可達對象(Reachable Objects),而無法被訪問到的對象則被視為垃圾(Garbage)。

GC Roots的典型來源包括

  • 全局對象(瀏覽器中的window,Node.js中的global
  • 當前執行棧中的局部變量和參數
  • 活動函數的上下文和閉包變量
  • DOM樹中的活動節點引用
  • 注冊的事件監聽器與回調函數
  • JavaScript內置對象的引用

在這里插入圖片描述

GC Roots
全局變量
執行棧變量
活動函數上下文
DOM樹引用
事件監聽器
對象1
對象2
對象3
對象4
對象5
對象6
對象7
對象8

2. 可達性判定過程

標記-清除算法的完整回收周期分為兩個關鍵階段:

(1) 標記階段(Marking Phase)
  1. 確定GC Roots:回收器識別當前所有根對象
  2. 深度優先遍歷:從根對象開始深度遍歷所有引用的子對象
  3. 標記存活對象:在對象頭中設置存活標記位
  4. 處理循環引用:通過標記狀態避免重復訪問
// 標記階段偽代碼
function markFromRoots() {// 獲取所有GC Rootsconst roots = getGCRoots();// 初始化工作隊列const worklist = [...roots];while (worklist.length > 0) {const current = worklist.pop();// 如果對象已被標記則跳過if (current.isMarked) continue;// 標記當前對象current.isMarked = true;// 遞歸處理所有引用對象const references = getReferences(current);for (const ref of references) {// 將子引用加入工作隊列worklist.push(ref);}}
}
(2) 清除階段(Sweeping Phase)
開始掃描堆
對象已標記?
清除標記位
釋放內存
移動至下一個對象
是否結束?
結束
// 清除階段偽代碼
function sweep() {let freedMemory = 0;let current = heap.firstObject;while (current) {if (!current.isMarked) {// 釋放未標記對象內存const size = getObjectSize(current);freedMemory += size;free(current);} else {// 重置標記位current.isMarked = false;}current = current.next;}return freedMemory;
}

3. 循環引用處理案例

標記-清除算法的重要優勢是能正確處理循環引用問題:

function createCycle() {let user = { name: "John" };let profile = { age: 30 };// 形成循環引用user.profile = profile;profile.user = user;return null;
}createCycle(); // 執行后對象失去可達性

在這個案例中:

  1. 函數執行后,userprofile都離開作用域
  2. 循環引用鏈斷開與GC Roots的連接
  3. 垃圾回收器識別為不可達對象
  4. 清除階段回收兩個對象的內存

二、Chrome DevTools Memory工具詳解

1. Memory工具核心功能

在這里插入圖片描述

Chrome DevTools的Memory面板是前端性能優化的利器,提供四種專業分析模式,每種模式都有其獨特的應用場景和優勢:

1.1 Heap Snapshot(堆快照)

核心功能:捕獲當前JavaScript堆內存的完整狀態快照,可以精確到每個對象的保留大小和引用關系。

典型應用場景

  • 分析內存中具體存在哪些對象
  • 排查內存泄漏問題的根源
  • 比較前后快照找出異常增長的對象

使用示例

  1. 頁面加載后立即拍攝快照
  2. 執行特定操作后拍攝快照
  3. 使用"Comparison"功能對比兩次快照差異

在這里插入圖片描述

在這里插入圖片描述

1.2 Allocation Timeline(分配時間線)

核心功能:實時記錄一段時間內的內存分配情況,并可視化顯示分配位置和時間。

典型應用場景

  • 定位高頻內存分配代碼
  • 發現臨時對象大量創建的問題
  • 分析動畫過程中的內存使用模式

工作流程

  1. 開始錄制
  2. 執行需要分析的操作
  3. 停止錄制并分析結果
  4. 重點關注藍色豎條(內存分配點)

在這里插入圖片描述

1.3 Allocation Sampling(分配采樣)

核心功能:通過統計學采樣方法監控內存分配,對性能影響極小。

典型應用場景

  • 生產環境內存監控
  • 長期運行的應用分析
  • 需要最小化性能影響的場景

優勢

  • 采樣頻率可調(默認50ms)
  • 不影響用戶體驗
  • 可運行較長時間

在這里插入圖片描述

1.4 Detached Elements(游離DOM元素)

核心功能:專門檢測已從DOM樹移除但仍被JavaScript引用的元素。

典型應用場景

  • 排查DOM節點內存泄漏
  • 檢測未正確清理的DOM引用
  • 分析單頁應用的路由切換問題

常見問題模式

  • 事件監聽器未移除
  • 全局變量持有DOM引用
  • 閉包意外捕獲DOM節點

在這里插入圖片描述

性能影響對比表
模式內存開銷CPU占用建議使用時長
Heap Snapshot高(需保存完整堆)短期(幾分鐘)
Allocation Timeline很高(記錄所有分配)很短(30秒內)
Allocation Sampling很低很低長期(數小時)
Detached Elements按需使用
Memory工具
Heap Snapshot
Allocation Timeline
Allocation Sampling
Detached Elements
對象統計
引用鏈分析
分配熱點定位
時序模式分析
長期監控
性能分析
DOM泄漏檢測
引用路徑追蹤

最佳實踐建議

  1. 開發階段優先使用Heap Snapshot進行詳細分析
  2. 性能測試時配合Allocation Timeline找出熱點
  3. 上線后使用Allocation Sampling進行監控
  4. 針對DOM相關問題時啟用Detached Elements檢測

2. 使用Heap Snapshot分析可達性

Heap Snapshot是分析對象可達性的黃金標準工具,它能完整記錄堆內存中的對象引用關系,幫助開發者精確識別未被垃圾回收的對象及其引用鏈。這種分析方法特別適用于解決難以察覺的內存泄露問題。

操作步驟詳解

  1. 打開Chrome DevTools(快捷鍵F12或Ctrl+Shift+I)
  2. 切換到Memory面板(新版可能在"Performance"或"Memory"標簽頁下)
  3. 在左側工具欄選擇"Heap snapshot"選項
  4. 點擊藍色的"Take snapshot"按鈕
  5. 等待快照完成(底部狀態欄會顯示進度)
  6. 快照處理完成后,在面板中會顯示內存使用統計圖表
  7. 點擊具體對象可展開其引用樹

在這里插入圖片描述

快照視圖核心字段深度解析

字段詳細說明內存分析意義典型應用場景
Constructor顯示對象的構造函數名稱,如Array、Object、自定義類名等快速定位特定類型的對象,如發現大量未釋放的閉包函數識別特定框架(如React組件)的內存占用
Distance表示從GC Roots(如window對象)到當前對象的引用層級數數值越大說明引用鏈越長,可能是深層嵌套的對象檢查意外保留的深層數據結構
Shallow Size對象自身占用的內存大小(不包括引用的對象)評估基礎對象的直接內存開銷分析基本數據類型的內存使用
Retained Size對象及其所有依賴對象占用的總內存揭示刪除該對象能釋放的總內存量定位內存泄露的主要來源
Retainers顯示保持對象存活的所有引用路徑(可展開查看完整鏈)追蹤內存泄露的根源引用解決循環引用問題

高級分析技巧

  1. 比較多個快照:先取初始快照,執行操作后再取快照,通過對比找出異常增長的對象
  2. 使用篩選器:在搜索框輸入*或特定構造函數名快速定位目標對象
  3. 關注大對象:按Retained Size排序,優先檢查占用內存最多的對象
  4. 分析DOM節點:檢查Detached DOM樹,這些是已從DOM移除但仍被JS引用的節點

常見問題識別模式

  • 內存泄露:連續快照中同類型對象數量持續增長
  • 緩存失控:過大或無限增長的Map/Set對象
  • 事件監聽泄露:大量重復的EventListener保留
  • 閉包問題:意外保留的function對象及其作用域鏈

3. 內存泄漏檢測實戰

場景描述:SPA應用中DOM元素泄漏

在單頁面應用(SPA)中,動態創建和銷毀DOM元素是常見操作。當這些元素沒有被正確清理時,會導致內存泄漏。

以下是一個典型的內存泄漏示例:

// 內存泄漏示例代碼
const leakedElements = new Set();  // 全局集合,用于緩存DOM元素function handleClick() {console.log('clicked');
}function renderComponent() {// 創建新的DOM元素const element = document.createElement('div');element.className = 'component';element.textContent = '動態組件';// 添加事件監聽器(未移除)element.addEventListener('click', handleClick);// 添加到全局集合(導致內存泄漏的關鍵)leakedElements.add(element);// 掛載到DOM樹document.body.appendChild(element);
}// 移除組件時未清理相關引用
function unmountComponent() {const elements = document.querySelectorAll('.component');elements.forEach(el => {// 僅從DOM樹中移除,但未清理事件監聽器和全局集合引用document.body.removeChild(el);});
}// 模擬多次渲染卸載(內存泄漏會隨著循環次數增加而累積)
for (let i = 0; i < 10; i++) {renderComponent();unmountComponent();
}

分析步驟

  1. 初始快照:在頁面初始化后拍攝基準快照(Snapshot 1),記錄初始內存狀態
  2. 執行操作:執行10次完整的渲染/卸載循環
  3. 強制GC:手動觸發垃圾回收(點擊Chrome DevTools中的"Collect garbage"按鈕)
  4. 操作后快照:拍攝操作后快照(Snapshot 2),捕獲內存變化
  5. 對比分析:在Comparison視圖中對比兩個快照的差異,重點關注:
    • 內存增長情況
    • 未被回收的對象
    • 保留路徑(Retainer)分析
記錄初始內存狀態
Snapshot 1
執行10次渲染/卸載循環
手動觸發垃圾回收
Snapshot 2
Comparison視圖對比分析
過濾Detached DOM元素
分析Retainer引用鏈
識別泄漏源頭
檢查游離DOM元素數量
查看全局變量引用
定位問題代碼

關鍵發現

  1. 內存增長模式:每次操作后內存持續線性增長,沒有回落到初始水平
  2. 泄漏對象:發現大量狀態為Detached的HTMLDivElement存在(預期應為0)
  3. 引用鏈分析:Retainer鏈顯示這些元素被leakedElements集合引用
  4. 附加問題:事件監聽器未被移除導致額外的內存占用
  5. 典型特征:Detached DOM樹的總大小與操作次數成正比

在這里插入圖片描述

4. 引用鏈分析與修復方案

泄漏原因分析

  1. 全局集合leakedElements保持對DOM元素的引用
  2. 事件監聽器未在元素移除前銷毀
  3. 卸載流程不完整,未清理相關引用

修復方案

// 使用WeakMap建立弱引用注冊表
// 鍵為DOM元素,值為組件元數據(自動隨元素銷毀而釋放)
const componentRegistry = new WeakMap();// 組件渲染函數(帶資源管理)
function renderComponent(config) {// 創建DOM元素const element = document.createElement('div');element.className = 'dynamic-component';// 使用AbortController統一管理事件監聽const controller = new AbortController();const { signal } = controller;// 安全添加事件監聽(可自動清理)element.addEventListener('click', handleClick, { signal });element.addEventListener('mouseover', trackHover, { signal });// 注冊組件元數據componentRegistry.set(element, {controller,children: [],  // 子組件引用observers: []  // 第三方觀察者});// 掛載到DOMdocument.getElementById('app').appendChild(element);return element;
}// 標準化的卸載流程
function unmountComponent(element) {if (!componentRegistry.has(element)) return;const { controller, children, observers } = componentRegistry.get(element);// 階段1:終止所有事件監聽controller.abort();// 階段2:清理子組件引用children.forEach(child => unmountComponent(child));// 階段3:釋放觀察者資源observers.forEach(obs => obs.disconnect());// 階段4:DOM移除element.remove();// WeakMap條目會自動刪除
}

三、標記-清除算法與Memory工具的結合應用

1. 識別虛假可達對象

在現代瀏覽器中,虛假可達對象(False Reachable Objects)是指那些從垃圾回收(GC)的“根對象”(如 windowdocument)出發在引用鏈上可達,但實際上已不再被使用的對象。這類對象因被意外保留而無法被回收,導致內存泄漏。

某些情況下對象理論上可回收但實際仍存在,常見于以下幾種場景:

// 閉包導致的意外引用
function createHeavyObject() {const largeBuffer = new ArrayBuffer(1024 * 1024 * 10); // 10MBreturn {process() {// 即使未使用largeBuffer,閉包仍保持引用console.log('Processing...');// 調試時可添加以下語句驗證// debugger;},// 顯式釋放方法release() {largeBuffer = null;}};
}const processor = createHeavyObject(); // 從 GC Root 可達
processor.process();
// processor.release(); // 未顯式釋放,導致無法 GC

在這里插入圖片描述

分析策略

  1. 在DevTools中多次調用函數并強制GC(通過Performance面板的垃圾回收按鈕)
  2. 對比Heap快照查看ArrayBuffer是否被回收(重點關注Shallow/Retained Size變化)
  3. 通過支配樹視圖定位持有者,特別檢查:
    • Closure作用域鏈
    • 全局變量引用
    • 事件監聽器
  4. 使用"Allocation on timeline"跟蹤內存分配路徑

2. 內存碎片化分析

標記-清除算法的缺點會導致內存碎片,典型現象包括:

連續堆內存 100MB
分配對象A:20MB, 對象B:30MB, 對象C:10MB
釋放對象B后形成30MB碎片
嘗試分配25MB對象D失敗
觸發GC壓縮或申請新內存頁
最終堆布局: A20MB + D25MB + 5MB碎片 + C10MB

在Memory工具中的具體操作:

  1. 查看Summary視圖的對象分布,重點關注:
    • 小對象(<1KB)的數量占比
    • 相同類型對象的Size分布離散程度
  2. 注意特殊標識:
    • (array):普通數組的碎片情況
    • (string):字符串的存儲碎片
    • (system):系統對象的保留空間
  3. 典型危險信號:
    • 存在大量1KB以下的小對象
    • 相同類型對象size差異巨大
    • "Detached DOM tree"等特殊碎片

優化策略

  • 對象池技術示例:
    class ObjectPool {constructor(createFn, size) {this.pool = Array(size).fill().map(createFn);this.index = 0;}get() {return this.pool[this.index++ % this.pool.length];}
    }
    
  • 使用TypedArray的最佳實踐:
    • 預分配足夠空間
    • 避免頻繁resize
    • 考慮使用SharedArrayBuffer多線程共享

3. 循環引用檢測實戰

// 復雜循環引用案例
class DataProcessor {constructor() {this.cache = new Map();this.initWebWorker();}initWebWorker() {this.worker = new Worker('processor.js');// 雙向引用this.worker.onmessage = (e) => this.handleMessage(e);}handleMessage(e) {// 將處理結果存入緩存this.cache.set(e.data.id, e.data);}process(data) {this.worker.postMessage(data);}// 缺少銷毀方法
}// 使用場景
const processor = new DataProcessor();
document.getElementById('start').addEventListener('click', () => {processor.process(getData());
});
// 頁面切換時未清理

在Heap Snapshot中的高級分析技巧:

  1. 使用"Containment"視圖逐層展開:
    • window → event listeners → handler → DataProcessor實例
  2. 應用"Dominators"視圖識別關鍵控制節點
  3. 對可疑對象右鍵選擇"Show in Summary view"查看詳細數據
  4. 使用"Comparison"模式對比操作前后的引用變化

企業級解決方案

interface Disposable {dispose(): void;
}class DataProcessor implements Disposable {private _disposed = false;dispose() {if (this._disposed) return;// 1. 終止Workerthis.worker.terminate();// 2. 清除緩存this.cache.clear();// 3. 移除事件監聽this.worker.onmessage = null;// 4. 標記為已銷毀this._disposed = true;// 5. 可選:添加調試信息if (DEBUG) console.log('[Memory] DataProcessor disposed');}// 添加析構保障~DataProcessor() {this.dispose();}
}// 使用WeakRef避免強引用
const processorRef = new WeakRef(new DataProcessor());

四、內存優化最佳實踐

1. 避免常見內存泄漏模式

四大內存泄漏類型

類型案例解決方案
全局變量leakedData = new Array(1000000)使用嚴格模式
閉包引用function outer() { const data = ...; return () => {...} }關鍵變量置null
DOM引用cache.set(element.id, element)WeakMap替代Map
未移除監聽器element.addEventListener(...)AbortController

2. 弱引用策略的應用

WeakMap與WeakSet應用場景:

// 1. DOM元素元數據存儲
const domMetadata = new WeakMap();function attachMetadata(element, data) {domMetadata.set(element, data);
}// 當element被回收時自動移除// 2. 對象緩存管理
const cache = new WeakMap();function processObject(obj) {if (!cache.has(obj)) {const result = computeResult(obj);cache.set(obj, result);}return cache.get(obj);
}// 3. 私有屬性實現
class PrivateData {constructor() {const data = { /* private */ };privates.set(this, data);}
}
const privates = new WeakMap();

3. 內存分析工作流設計

高效內存分析流程

建立基準
模擬用戶操作
強制垃圾回收
拍攝快照
內存增長>10%?
分析堆快照
繼續測試
定位可疑對象
分析保留路徑
修復問題
回歸測試

推薦工具鏈整合

  • 開發階段:Chrome DevTools Memory面板
  • CI/CD集成:Puppeteer內存監控腳本
  • 生產監控:Web Vitals內存指標上報
  • 性能測試:Lighthouse內存審計

五、高級內存分析技巧

1. 支配樹分析技術

支配樹視圖展示了對象間的支配關系

GC Roots
Window
Document
DOM Tree
Detached Element
渲染引擎對象
JS引用對象
泄漏數據

操作流程

  1. 在Heap Snapshot中選擇Dominators視圖
  2. 按Retained Size降序排列
  3. 定位持有大量內存的對象節點
  4. 分析子樹判斷必要性

2. 時間線分配分析

2025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-032025-08-03點擊按鈕 JS堆分配 滾動頁面 DOM分配 事件監聽 輸入表單 用戶操作內存分配內存分配時間線

操作步驟

  1. 開啟Allocation instrumentation on timeline
  2. 執行用戶操作序列
  3. 停止記錄查看結果
  4. 重點關注:
    • 紅色豎條(未回收內存)
    • 高頻分配對象類型
    • 操作與分配的對應關系

3. 內存壓力測試方案

自動化測試腳本

const puppeteer = require('puppeteer');async function runMemoryTest() {const browser = await puppeteer.launch();const page = await browser.newPage();// 1. 設置性能監控await page.tracing.start({path: 'profile.json'});await page.goto('http://your-app.com');// 2. 重復執行關鍵操作for (let i = 0; i < 100; i++) {await page.click('#action-button');await page.waitForTimeout(500);// 定期收集內存指標if (i % 10 === 0) {const metrics = await page.metrics();console.log(`[${i}] JSHeapUsed: ${metrics.JSHeapUsedSize}`);}}// 3. 生成分析報告await page.tracing.stop();await browser.close();
}runMemoryTest();

關鍵監控指標

  • JSHeapUsedSize:已使用JS堆大小
  • JSHeapTotalSize:總JS堆大小
  • NodesCount:DOM節點總數
  • ListenerCount:事件監聽器總數

總結

標記-清除算法是現代JavaScript引擎內存管理的核心,通過可達性判定自動回收不再使用的內存空間。該算法從GC Roots出發遍歷對象圖,標記所有可達對象,在清除階段回收未標記內存空間,高效處理循環引用等復雜場景。

Chrome DevTools Memory工具提供了一套完整的分析方案:

  • Heap Snapshot用于靜態分析對象引用關系
  • Allocation timeline監控內存動態分配
  • Dominators tree揭示內存瓶頸根源

通過本文的實踐指導,開發者可以:

  1. 深入理解垃圾回收機制的工作原理
  2. 掌握Memory工具的操作技巧與分析思路
  3. 識別并修復常見的內存泄漏模式
  4. 實現高效的內存監控與優化工作流
  5. 預防性設計內存友好的應用架構

持續的內存監控與優化應成為現代Web開發的核心實踐,從而構建高性能、高穩定性的JavaScript應用。

參考資源

  1. Understanding Weak References in JS
  2. DOM Memory Leak Patterns

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

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

相關文章

微算法科技(NASDAQ:MLGO)基于量子重加密技術構建區塊鏈數據共享解決方案

隨著信息技術的飛速發展&#xff0c;數據已成為數字經濟時代的核心生產要素。數據的共享和安全往往是一對難以調和的矛盾。傳統的加密方法在面對日益強大的計算能力和復雜的網絡攻擊時&#xff0c;安全性受到了挑戰。微算法科技(NASDAQ&#xff1a;MLGO)通過引入量子重加密技術…

FastAPI快速入門P2:與SpringBoot比較

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄引言1 FastAPI事件管理2 類的使用2.1 初始化方法對…

SAP-ABAP: Open SQL集合函數COUNT(統計行數)、SUM(數值求和)、AVG(平均值)、MAX/MIN(極值)深度指南

SAP Open SQL集合函數深度指南 1. 核心價值與特性函數作用關鍵特性COUNT統計行數用COUNT(*)包含NULL值行&#xff0c;COUNT(字段)排除NULLSUM數值求和自動過濾NULL值&#xff0c;結果類型與源字段相同AVG平均值必須用TYPE f接收&#xff0c;否則四舍五入導致精度丟失MAX/MIN極值…

【docker】UnionFS聯合操作系統

Linux 的 Namespace、CGroups 和 UnionFS 三大技術支撐了 Docker 的實現。 一、為什么需要聯合文件系統&#xff1f;在傳統操作系統中&#xff0c;每個文件系統都是獨立的孤島。但當我們需要&#xff1a;合并多個目錄的內容保持基礎系統不變的同時進行修改高效共享重復文件內容…

CTF-XXE 漏洞解題思路總結

一、XXE 漏洞簡介XXE (XML External Entity) 漏洞允許攻擊者通過構造惡意的 XML 輸入&#xff0c;強迫服務器的 XML 解析器執行非預期的操作。在 CTF 場景中&#xff0c;最常見的利用方式是讓解析器讀取服務器上的敏感文件&#xff0c;并將其內容返回給攻擊者。二、核心攻擊載荷…

GitLab:一站式 DevOps 平臺的全方位解析

GitLab&#xff1a;一站式 DevOps 平臺的全方位解析 在當今數字化時代&#xff0c;軟件研發的效率與質量直接決定企業的市場競爭力。GitLab 作為全球領先的 DevOps 平臺&#xff0c;憑借 “從構思到部署” 的全流程管理能力&#xff0c;已成為無數企業加速軟件交付的核心工具。…

Flink富函數:一種更靈活、可擴展的方式來定義數據流的處理邏輯

本文重點 Flink中的富函數類是一組用于處理數據流的函數接口和實現類。富函數類提供了一種更靈活和可擴展的方式來定義數據流的處理邏輯。 富函數類 富函數類是DataStream API提供的一個函數類的接口,所有的Flink函數類都有其Rich版本。富函數類一般是以抽象類的形式出現的。…

【STM32】HAL庫中的實現(四):RTC (實時時鐘)

&#x1f552;HAL庫中的實現&#xff1a;RTC&#xff08;Real-Time Clock&#xff09;實時時鐘RTC 是 STM32 的低功耗實時時鐘模塊&#xff0c;常用于&#xff1a; 實時時間維護&#xff08;年月日時分秒&#xff09;定時喚醒日志時間戳鬧鐘功能RTC&#xff08;實時時鐘&#x…

Pauli 矩陣指數函數展開為顯式矩陣 e^A -> B

要展開表達式 為普通矩陣&#xff0c;其中 是 Pauli 矩陣&#xff0c; 是單位向量&#xff0c; 是實數。以下是詳細推導步驟&#xff1a;1. Pauli 矩陣的性質Pauli 矩陣定義為&#xff1a;它們滿足以下關系&#xff1a;?其中 是 Kronecker delta&#xff0c;? 是 Levi-…

【Algorithm | 0x03 搜索與圖論】DFS

DFS基礎知識典型例題例1&#xff1a;n皇后問題例2&#xff1a;拍照例3&#xff1a;理發基礎知識 核心原理&#xff1a;一條路走到黑 示意圖&#xff1a;其含義表示&#xff0c;在這個圖中頂層是第0層&#xff0c;也就是后面dfs的入口&#xff0c;一般從dfs(0)開始操作。 模版&a…

Redis的數據過期策略有哪些?

Redis內部通過兩種主要策略來處理過期的Key&#xff1a; 惰性刪除 惰性刪除&#xff1a;顧明思議并不是在TTL到期后就立刻刪除&#xff0c;而是在訪問一個key的時候&#xff0c;Redis會先檢查這個鍵是否過期。如果過期&#xff0c;就刪除它&#xff0c;然后返回nil。 這種方式非…

水庫雨水情測報和大壩安全監測系統解決方案

一、方案背景 在全球氣候變化和極端天氣頻發的背景下&#xff0c;水庫作為重要的水利設施&#xff0c;承擔著防洪、供水、灌溉、發電等多重功能。然而&#xff0c;由于水庫蓄水量巨大&#xff0c;一旦發生潰壩或運行異常&#xff0c;將對下游地區造成不可估量的生命財產損失。因…

BFS 和 DFS 編程思想、框架、技巧及經典例題總結

BFS 和 DFS 編程思想、框架、技巧及經典例題總結 一、核心編程思想 BFS&#xff08;廣度優先搜索&#xff09; 核心思想&#xff1a;以「層次遍歷」為核心&#xff0c;從起點出發&#xff0c;優先探索距離起點最近的節點&#xff0c;逐層擴散遍歷。本質&#xff1a;通過「隊列」…

【面試場景題】日志去重與統計系統設計

文章目錄題目場景描述要求問題考察點解答思考一、核心解決方案&#xff08;基礎版&#xff0c;單節點32GB內存、10臺節點&#xff09;1. 整體架構選型2. 關鍵步驟詳解&#xff08;1&#xff09;數據分片&#xff1a;解決“數據量大&#xff0c;單節點處理不了”的問題&#xff…

【Day 16】Linux-性能查看

目錄 一、Stress系統壓力測試工具 二、性能查看 &#xff08;一&#xff09;查看CPU # nproc # lscpu # top # uptime # mpstat 數字1 數字2 &#xff08;二&#xff09;查看內存 # dmidecode -t memory | less # free -h # …

【ICCV2017】Deformable Convolutional Networks

一、摘要盡管卷積神經網絡&#xff08;CNN&#xff09;在視覺識別任務上取得巨大成功&#xff0c;但其固有的固定幾何結構&#xff08;固定卷積采樣網格、固定池化窗口、固定 RoI 劃分&#xff09;嚴重限制了對未知幾何變換&#xff08;尺度、姿態、形變、視角變化&#xff09;…

echarts在前后端分離項目中的實踐與應用

目錄 一、ECharts簡介 二、后端數據接口設計 三、數據結構設計 1. 柱狀圖數據結構 2. 餅圖數據結構 四、后端實現要點 五、前端ECharts配置解析 1. 柱狀圖配置 2. 餅圖配置 六、最佳實踐建議 七、總結 一、ECharts簡介 ECharts是百度開源的一個基于JavaScript的可視…

SQL 四大語言分類詳解:DDL、DML、DCL、DQL

SQL&#xff08;結構化查詢語言&#xff09;通常被分為四種主要類型&#xff0c;每種類型負責不同的數據庫操作。下面我將詳細介紹這四類SQL語言的語法和用途。一、DDL (Data Definition Language) 數據定義語言功能&#xff1a;定義和管理數據庫對象結構&#xff08;表、視圖、…

ESP-idf框架下的HTTP服務器\HTML 485溫濕度采集并長傳

項目描述:本項目采用485采集溫濕度以及電壓電流等,485模塊分別為下圖,串口轉485模塊采用自動收發模塊,ESP32工作在AP熱點模式,通過手機連接esp32的熱點來和esp進行數據通訊,使用esp32作為HTTP服務器缺陷:項目的最終HTML頁面代碼可發給AI讓其寫注釋#include "freertos/Free…

雅江工程解鎖墨脫秘境:基礎條件全展示(區位、地震、景點、天氣)

目錄 前言 一、區位信息 1、空間位置 2、區位介紹 二、地震信息 1、歷史地震信息 2、5.0級以上大地震 三、景點信息 1、景點列表分布 2、4A級以上景點 四、天氣信息 1、天氣實況 2、天氣應對挑戰 五、總結 前言 相信最近大家對雅江電站的超級大工程項目應該有所耳…