日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一篇帶給你V8global.gc()的實現(xiàn)

前言:在 Node.js 中我們有時候會使用 global.gc() 主動觸發(fā) gc 來測試一些代碼,因為我們知道 V8 gc 的執(zhí)行時機是不定的。但是可能很少同學知道 global.gc() 的實現(xiàn),本文介紹一些在 V8 中關于這部分的實現(xiàn)。

創(chuàng)新互聯(lián)公司是一家專業(yè)提供邗江企業(yè)網(wǎng)站建設,專注與做網(wǎng)站、成都網(wǎng)站設計、H5高端網(wǎng)站建設、小程序制作等業(yè)務。10年已為邗江眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡公司優(yōu)惠進行中。

了解 global.gc() 實現(xiàn)之前,首先看一下 V8 的 Extension 機制。Extension 機制用于拓展 V8 的能力。在 V8 初始化的過程中,V8::Initialize 會初始化 Extension 機制,具體在 Bootstrapper::InitializeOncePerProcess 中。

void Bootstrapper::InitializeOncePerProcess() {
v8::RegisterExtension(std::make_unique(GCFunctionName()));
v8::RegisterExtension(std::make_unique());
v8::RegisterExtension(std::make_unique());
v8::RegisterExtension(std::make_unique());
v8::RegisterExtension(std::make_unique());
}

V8 通過 RegisterExtension 注冊了多個 Extension。

void RegisterExtension(std::unique_ptr extension) {
RegisteredExtension::Register(std::move(extension));
}

void RegisteredExtension::Register(std::unique_ptr extension) {
RegisteredExtension* new_extension = new RegisteredExtension(std::move(extension));
new_extension->next_ = first_extension_;
first_extension_ = new_extension;
}

執(zhí)行完 Register 后就形成了一個 Extension 鏈表,RegisteredExtension 對象只是對 Extension 對象的簡單封裝,它內(nèi)部持有 Extension 對象和一個鏈表 next 指針,另外還有一個全局的對象 first_extension_ 指向鏈表頭部。注冊完 Extension 后,接下來看看初始化 Extension 的邏輯。具體的調(diào)用鏈是 NewContext -> CreateEnvironment -> InvokeBootstrapper.Invoke -> Bootstrapper::CreateEnvironment -> InstallExtensions -> Genesis::InstallExtensions。

bool Genesis::InstallExtensions(Isolate* isolate,
Handle native_context,
v8::ExtensionConfiguration* extensions) {
ExtensionStates extension_states;
return InstallAutoExtensions(isolate, &extension_states) &&
(!FLAG_expose_gc || InstallExtension(isolate, "v8/gc", &extension_states))
}

當啟動 V8 的時候設置了 expose_gc 標記,那么就會執(zhí)行 InstallExtension。

bool Genesis::InstallExtension(Isolate* isolate,
v8::RegisteredExtension* current,
ExtensionStates* extension_states) {
HandleScope scope(isolate);
extension_states->set_state(current, VISITED);
v8::Extension* extension = current->extension();
// 安裝依賴
for (int i = 0; i < extension->dependency_count(); i++) {
if (!InstallExtension(isolate, extension->dependencies()[i],
extension_states)) {
return false;
}
}
// 編譯 Extension
CompileExtension(isolate, extension);
extension_states->set_state(current, INSTALLED);
return true;
}

至此就完成了 Extension 的安裝。接下來具體看一下 global.gc() 對應的具體實現(xiàn)。

class V8_EXPORT Extension {
public:
Extension(const char* name, const char* source = nullptr, int dep_count = 0,
const char** deps = nullptr, int source_length = -1);
virtual ~Extension() { delete source_; }
virtual Local GetNativeFunctionTemplate(
Isolate* isolate, Local name) {
return Local();
}

const char* name() const { return name_; }
size_t source_length() const { return source_length_; }
const String::ExternalOneByteStringResource* source() const {
return source_;
}
int dependency_count() const { return dep_count_; }
const char** dependencies() const { return deps_; }
void set_auto_enable(bool value) { auto_enable_ = value; }
bool auto_enable() { return auto_enable_; }

// Disallow copying and assigning.
Extension(const Extension&) = delete;
void operator=(const Extension&) = delete;

private:
const char* name_;
size_t source_length_; // expected to initialize before source_
String::ExternalOneByteStringResource* source_;
int dep_count_;
const char** deps_;
bool auto_enable_;
};

Extension 是 Extension 機制的基類,從上面代碼中我們可以大致了解到一個 Extension 需要實現(xiàn)什么。接著看 gc Extension 的實現(xiàn)。

class GCExtension : public v8::Extension {
public:
explicit GCExtension(const char* fun_name)
: v8::Extension("v8/gc", BuildSource(buffer_, sizeof(buffer_), fun_name)) {}
v8::Local GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local name) override;

static void GC(const v8::FunctionCallbackInfo& args);

private:
static const char* BuildSource(char* buf, size_t size, const char* fun_name) {
base::SNPrintF(base::Vector(buf, static_cast(size)),
"native function %s();", fun_name);
return buf;
}

char buffer_[50];
};

在 bytecode-generator.cc 中有以下代碼。

 v8::Local info = expr->extension()->GetNativeFunctionTemplate(v8_isolate, Utils::ToLocal(expr->name()));

所以我們來看一下 GetNativeFunctionTemplate。

首先看 GetNativeFunctionTemplate。
```c
v8::Local GCExtension::GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local str) {
return v8::FunctionTemplate::New(isolate, GCExtension::GC);
}

大致就是當我們執(zhí)行 global.gc() 時就會執(zhí)行 GCExtension::GC 函數(shù)。

void GCExtension::GC(const v8::FunctionCallbackInfo& args) {
v8::Isolate* isolate = args.GetIsolate();
// 沒有參數(shù)則同步執(zhí)行 kFullGarbageCollection gc,即執(zhí)行 global.gc() 時
if (args.Length() == 0) {
InvokeGC(isolate, ExecutionType::kSync,
v8::Isolate::GarbageCollectionType::kFullGarbageCollection);
return;
}
auto maybe_options = Parse(isolate, args);
if (maybe_options.IsNothing()) return;
GCOptions options = maybe_options.ToChecked();
// 否則根據(jù)參數(shù)處理
switch (options.execution) {
case ExecutionType::kSync:
InvokeGC(isolate, ExecutionType::kSync, options.type);
break;
case ExecutionType::kAsync: {
v8::HandleScope scope(isolate);
auto resolver = v8::Promise::Resolver::New(isolate->GetCurrentContext())
.ToLocalChecked();
args.GetReturnValue().Set(resolver->GetPromise());
auto task_runner =
V8::GetCurrentPlatform()->GetForegroundTaskRunner(isolate);
CHECK(task_runner->NonNestableTasksEnabled());
task_runner->PostNonNestableTask(
std::make_unique(isolate, resolver, options.type));
} break;
}
}

從這個函數(shù)中我們可以知道,global.gc 函數(shù)是可以帶參數(shù)的,參數(shù)可以控制 gc 是同步還是異步,還可以控制 gc 的類型,我們知道 V8 里針對不同的 space 有不同的 gc 策略。參數(shù)的具體函數(shù)使用可以參考。

Provides garbage collection on invoking |fun_name|(options), where
- options is a dictionary like object. See supported properties below.
- no parameter refers to options:
{type: 'major', execution: 'sync'}.
- truthy parameter that is not setting any options:
{type: 'minor', execution: 'sync'}.

Supported options:
- type: 'major' or 'minor' for full GC and Scavenge, respectively.
- execution: 'sync' or 'async' for synchronous and asynchronous execution,
respectively.
- Defaults to {type: 'major', execution: 'sync'}.

Returns a Promise that resolves when GC is done when asynchronous execution
is requested, and undefined otherwise.

繼續(xù)看核心函數(shù) InvokeGC。

void InvokeGC(v8::Isolate* isolate, ExecutionType execution_type,
v8::Isolate::GarbageCollectionType type) {
Heap* heap = reinterpret_cast(isolate)->heap();
switch (type) {
case v8::Isolate::GarbageCollectionType::kMinorGarbageCollection:
heap->CollectGarbage(i::NEW_SPACE, i::GarbageCollectionReason::kTesting,
kGCCallbackFlagForced);
break;
case v8::Isolate::GarbageCollectionType::kFullGarbageCollection:
EmbedderStackStateScope stack_scope(
heap,
execution_type == ExecutionType::kAsync
? EmbedderStackStateScope::kImplicitThroughTask
: EmbedderStackStateScope::kExplicitInvocation,
execution_type == ExecutionType::kAsync
? v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers
: v8::EmbedderHeapTracer::EmbedderStackState::
kMayContainHeapPointers);
heap->PreciseCollectAllGarbage(i::Heap::kNoGCFlags,
i::GarbageCollectionReason::kTesting,
kGCCallbackFlagForced);
break;
}
}

InvokeGC 就是根據(jù)同步的參數(shù)去調(diào) heap 對象的 gc 接口從而做不同類型的 gc 回收。這就是 global.gc 的大致實現(xiàn)。

除此之外,還有其他 Extension,我們也可以自己寫拓展,不過有點限制的是需要在 V8 初始化時就設置需要安裝的 Extension。例如我們可以設置 expose_statistics 標記,然后通過全局函數(shù)收集堆信息(不同的 V8 版本支持的不一樣)。

node -expose_statistics -e "console.log(global.getV8Statistics())"

另外 V8 內(nèi)部也實現(xiàn)了一些 Extension,包括內(nèi)置的和一些 Demo,有興趣的同學可以自行查看。


當前標題:一篇帶給你V8global.gc()的實現(xiàn)
文章網(wǎng)址:http://www.dlmjj.cn/article/dpdicee.html