日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

V8 垃圾回收

發布時間:2025/3/20 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 V8 垃圾回收 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: https://github.com/yjhjstz/deep-into-node

垃圾回收器是一把十足的雙刃劍。好處是簡化程序的內存管理,內存管理無需程序員來操作,由此也減少了長時間運轉的程序的內存泄漏。然而無法預期的停頓,影響了交互體驗。本文從 V8 (node.js runtime) 的角度分析垃圾回收策略。

基本概念

垃圾回收器解決基本問題就是,識別需要回收的內存。一旦辨別完畢,這些內存區域即可在未來的分配中重用,或者是返還給操作系統。一個對象當它不是處于活躍狀態的時候它就死了。一個對象處于活躍狀態,當且僅當它被一個根對象或另一個活躍對象指向。根對象被定義為處于活躍狀態,是瀏覽器或V8所引用的對象。比如說全局對象屬于根對象,因為它們始終可被訪問;瀏覽器對象,如DOM元素,也屬于根對象,盡管在某些場合下它們只是弱引用。

堆的構成

在深入研究垃圾回收器的內部工作原理之前,首先來看看堆是如何組織的。V8將堆分為了幾個不同的區域:

新生區:大多數對象開始時被分配在這里。新生區是一個很小的區域,垃圾回收在這個區域非常頻繁,與其他區域相獨立。

老生指針區:包含大多數可能存在指向其他對象的指針的對象。大多數在新生區存活一段時間之后的對象都會被挪到這里。

老生數據區:這里存放只包含原始數據的對象(這些對象沒有指向其他對象的指針)。字符串、封箱的數字以及未封箱的雙精度數字數組,在新生區經歷一次 Scavenge 后會被移動到這里。

大對象區:這里存放體積超過1MB大小的對象。每個對象有自己mmap產生的內存。垃圾回收器從不移動大對象。

Code區:代碼對象,也就是包含JIT之后指令的對象,會被分配到這里。

Cell區、屬性Cell區、Map區:這些區域存放Cell、屬性Cell和Map,每個區域因為都是存放相同大小的元素,因此內存結構很簡單。

如上圖:在 node-v4.x 之后,區域進行了合并為:新生區,老生區,大對象區,Map區,Code區

有了這些背景知識,我們可以來深入垃圾回收器了。

識別指針

垃圾回收器面臨的第一個問題是,如何才能在堆中區分指針和數據,因為指針指向著活躍的對象。大多數垃圾回收算法會將對象在內存中挪動(以便減少內存碎片,使內存緊湊),因此即使不區分指針和數據,我們也常常需要對指針進行改寫。
V8采用了標記指針法:這種方法需要在每個指針的末位預留一位來標記這個字代表的是指針或數據。

寫屏障

如果新生區中某個對象,只有一個指向它的指針,而這個指針恰好是在老生區的對象當中,我們如何才能知道新生區中那個對象是活躍的呢? 為了解決這個問題,實際上在寫緩沖區中有一個列表 store-buffer{.cc,.h,-inl.h},列表中記錄了所有老生區對象指向新生區的情況。新對象誕生的時候,并不會有指向它的指針,而當有老生區中的對象出現指向新生區對象的指針時,我們便記錄下來這樣的跨區指向。由于這種記錄行為總是發生在寫操作時,它被稱為寫屏障.

垃圾回收三部曲

Stop-the-World 的GC包括三個主要步驟:

  • 枚舉根節點引用;
  • 發現并標記活對象;
  • 垃圾內存清理
  • 分代回收在 V8中分為Scavenge, Mark-Sweep。

    • Scavenge: 當分配指針達到了新生區的末尾,就會有一次清理。
    • Mark-Sweep: 對于活躍超過2個小周期的對象,則需將其移動至老生區, 當老生區有足夠多的對象時才會觸發。

    Scavenge

    void Heap::Scavenge() {RelocationLock relocation_lock(this);AlwaysAllocateScope scope(isolate());gc_state_ = SCAVENGE;// Clear descriptor cache.isolate_->descriptor_lookup_cache()->Clear();// Used for updating survived_since_last_expansion_ at function end.intptr_t survived_watermark = PromotedSpaceSizeOfObjects();SelectScavengingVisitorsTable();PrepareArrayBufferDiscoveryInNewSpace();// Flip the semispaces. After flipping, to space is empty, from space has// live objects.new_space_.Flip(); // 交換 SemiSpacenew_space_.ResetAllocationInfo(); // 重設分配指針Address new_space_front = new_space_.ToSpaceStart();promotion_queue_.Initialize(); // 晉升隊列ScavengeVisitor scavenge_visitor(this); // Scavenge迭代器// Copy roots. 枚舉跟對象IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); // Copy objects reachable from the old generation.{StoreBufferRebuildScope scope(this, store_buffer(),&ScavengeStoreBufferCallback);store_buffer()->IteratePointersToNewSpace(&ScavengeObject);}// Copy objects reachable from the encountered weak collections list.scavenge_visitor.VisitPointer(&encountered_weak_collections_);// Copy objects reachable from the encountered weak cells.scavenge_visitor.VisitPointer(&encountered_weak_cells_);// Copy objects reachable from the code flushing candidates list.MarkCompactCollector* collector = mark_compact_collector();if (collector->is_code_flushing_enabled()) {collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor);}// DoScavenge 處理晉升new_space_front = DoScavenge(&scavenge_visitor, new_space_front);while (isolate()->global_handles()->IterateObjectGroups(&scavenge_visitor, &IsUnscavengedHeapObject)) {new_space_front = DoScavenge(&scavenge_visitor, new_space_front);}isolate()->global_handles()->RemoveObjectGroups();isolate()->global_handles()->RemoveImplicitRefGroups();isolate()->global_handles()->IdentifyNewSpaceWeakIndependentHandles(&IsUnscavengedHeapObject);isolate()->global_handles()->IterateNewSpaceWeakIndependentRoots(&scavenge_visitor);new_space_front = DoScavenge(&scavenge_visitor, new_space_front);UpdateNewSpaceReferencesInExternalStringTable(&UpdateNewSpaceReferenceInExternalStringTableEntry);promotion_queue_.Destroy();incremental_marking()->UpdateMarkingDequeAfterScavenge();ScavengeWeakObjectRetainer weak_object_retainer(this);ProcessYoungWeakReferences(&weak_object_retainer);DCHECK(new_space_front == new_space_.top());// Set age mark.new_space_.set_age_mark(new_space_.top());new_space_.LowerInlineAllocationLimit(new_space_.inline_allocation_limit_step());FreeDeadArrayBuffers(true);// Update how much has survived scavenge.IncrementYoungSurvivorsCounter(static_cast<int>((PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size()));gc_state_ = NOT_IN_GC; }

    這個算法大致是,新生區被劃分為兩個等大的SemiSpace:出區、入區。絕大多數內存的分配都會在出區發生(但某些特定類型的對象,如可執行的代碼對象是分配在老生區的),當出區耗盡時,我們交換出區和入區(這樣所有的對象都歸屬在入區當中),然后將入區中活躍的對象復制至出區或晉升到老生區中,其中標記的過程實際是深度優先搜索。

    “標記-清除”算法

    void MarkCompactCollector::CollectGarbage() {DCHECK(state_ == PREPARE_GC);MarkLiveObjects(); //枚舉并標記活對象DCHECK(heap_->incremental_marking()->IsStopped());// ClearNonLiveReferences can deoptimize code in dependent code arrays.// Process weak cells before so that weak cells in dependent code// arrays are cleared or contain only live code objects.ProcessAndClearWeakCells();ClearNonLiveReferences();ClearWeakCollections();heap_->set_encountered_weak_cells(Smi::FromInt(0));ClearInvalidStoreAndSlotsBufferEntries();SweepSpaces(); // 按不同的空間劃分清理Finish();if (marking_parity_ == EVEN_MARKING_PARITY) {marking_parity_ = ODD_MARKING_PARITY;} else {DCHECK(marking_parity_ == ODD_MARKING_PARITY);marking_parity_ = EVEN_MARKING_PARITY;} }

    Scavenge算法對于快速回收、緊縮小片內存效果很好,但對于大片內存則消耗過大。頻繁的拷貝對于 CPU 是不可承受之重。老生區包含有上百MB的數據,對于這么大的區域,我們采取“標記-清除”算法與“標記-緊縮”算法。

    標記算法執行完畢后,我們可以選擇清理或是緊縮,這兩個算法都可以回收內存。

    • 清理算法非常簡單,只需遍歷頁的位圖,搜索連續的死對象釋放,時間久了會形成內存碎片。
    • 緊縮算法會嘗試將對象從碎片頁(包含大量小空閑內存的頁)中遷移整合在一起,來釋放內存。這些對象會被遷移到另外的頁上,因此也可能會新分配一些頁。alinode 對此策略進行了優化,使用 alinode runtime 即可享受到。

    總結

    垃圾回收非常復雜,alinode 提供了詳細的 GC 監控,幫助您分析把控性能。

    總結

    以上是生活随笔為你收集整理的V8 垃圾回收的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产又黄又粗又硬 | 91丨porny在线| 久久久资源网 | 成人免费黄 | 日韩av无码一区二区三区不卡 | 青青青青在线 | 国产精品黑人一区二区三区 | 动漫涩涩免费网站在线看 | 正在播放木下凛凛88av | 干综合网 | 污视频91 | 欧美a天堂 | 国产妞干网 | 国产精品久久久久久久专区 | 九九热最新网址 | 嫩草视频在线观看 | 青青草原综合网 | 亚洲国产成人精品激情在线 | av不卡在线免费观看 | 九九爱爱视频 | 人妻饥渴偷公乱中文字幕 | 好吊操精品视频 | 亚洲日本一区二区 | 人人艹在线| 狠狠爱夜夜 | 一区国产精品 | 久久久久黄色 | 国产福利视频导航 | 嫩草一区二区三区 | 国产综合内射日韩久 | 亚洲国产成人精品无码区99 | 91色蝌蚪| 亚洲国产毛片aaaaa无费看 | a级黄色片免费看 | 精精国产xxxx视频在线播放 | 亚洲AV无码成人精品国产一区 | 免费麻豆国产一区二区三区四区 | 少妇愉情理伦片bd | 国产超级av| 中文天堂在线资源 | 不卡av在线免费观看 | 大j8黑人w巨大888a片 | 婷婷综合av | 91麻豆国产在线观看 | 日本一区二区免费电影 | 99久久精品国产毛片 | 国产精品久久久久毛片大屁完整版 | 亚洲欧美国产精品 | 国产成人综合视频 | 国产乱人乱偷精品视频a人人澡 | 亚洲午夜精品久久久久久人妖 | 深夜福利网 | 欧美另类视频在线观看 | 清纯唯美亚洲色图 | 亚洲综合色视频 | 午夜免费视频观看 | 妺妺窝人体色www在线小说 | 日韩欧美国产一区二区在线观看 | 欧美一级免费看 | 欧美综合视频 | 国产草草影院 | 亚洲精品一卡二卡 | 日本少妇一区 | 一区二区欧美在线 | 欧洲亚洲综合 | 亚洲色图丝袜美腿 | 亚洲 欧美 中文字幕 | 日韩成人午夜 | 日韩在线免费观看视频 | 97超碰免费在线 | 黄色a级片网站 | 少妇无套高潮一二三区 | 老司机午夜性大片 | 国产免费一区二区三区最新6 | 91网在线| 孕妇丨91丨九色 | 欧美激情自拍偷拍 | 国产私密视频 | 伊人精品影院 | 国产成人av一区二区三区在线观看 | 在线观看第一页 | 青草视频在线看 | 91麻豆国产在线 | 国产成人av网站 | 九九九国产视频 | 一级肉体全黄裸片 | 国产精品5区 | 国产第一网站 | 国产aa | 亚洲成人欧美 | 91伊人久久 | 中文字幕一区二区三区四区五区 | 草民午夜理伦三级 | 婷婷激情五月 | 九九久久九九久久 | 好吊视频一区二区三区四区 | 日韩成人精品一区 | 97超碰色 | 色播激情网|