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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何加快 Node.js 应用的启动速度

發(fā)布時(shí)間:2024/8/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何加快 Node.js 应用的启动速度 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們平時(shí)在開(kāi)發(fā)部署 Node.js 應(yīng)用的過(guò)程中,對(duì)于應(yīng)用進(jìn)程啟動(dòng)的耗時(shí)很少有人會(huì)關(guān)注,大多數(shù)的應(yīng)用 5 分鐘左右就可以啟動(dòng)完成,這個(gè)過(guò)程中會(huì)涉及到和集團(tuán)很多系統(tǒng)的交互,這個(gè)耗時(shí)看起來(lái)也沒(méi)有什么問(wèn)題。

目前,集團(tuán) Serverless 大潮已至,Node.js serverless-runtime 作為前端新研發(fā)模式的基石,也發(fā)展的如火如荼。Serverless 的優(yōu)勢(shì)在于彈性、高效、經(jīng)濟(jì),如果我們的 Node.js FaaS 還像應(yīng)用一樣,一次部署耗時(shí)在分鐘級(jí),無(wú)法快速、有效地響應(yīng)請(qǐng)求,甚至在脈沖請(qǐng)求時(shí)引發(fā)資源雪崩,那么一切的優(yōu)勢(shì)都將變成災(zāi)難。

所有提供 Node.js FaaS 能力的平臺(tái),都在絞盡腦汁的把冷/熱啟動(dòng)的時(shí)間縮短,這里面除了在流程、資源分配等底層基建的優(yōu)化外,作為其中提供服務(wù)的關(guān)鍵一環(huán) —— Node.js 函數(shù),本身也應(yīng)該參與到這場(chǎng)時(shí)間攻堅(jiān)戰(zhàn)中。

Faas平臺(tái)從接到請(qǐng)求到啟動(dòng)業(yè)務(wù)容器并能夠響應(yīng)請(qǐng)求的這個(gè)時(shí)間必須足夠短,當(dāng)前的總目標(biāo)是 500ms,那么分解到函數(shù)運(yùn)行時(shí)的目標(biāo)是 100ms。這 100ms 包括了 Node.js 運(yùn)行時(shí)、函數(shù)運(yùn)行時(shí)、函數(shù)框架啟動(dòng)到能夠響應(yīng)請(qǐng)求的時(shí)間。巧的是,人類(lèi)反應(yīng)速度的極限目前科學(xué)界公認(rèn)為 100ms。

Node.js 有多快

在我們印象中 Node.js 是比較快的,敲一段代碼,馬上就可以執(zhí)行出結(jié)果。那么到底有多快呢?

以最簡(jiǎn)單的 console.log 為例(例一),代碼如下:

// console.js console.log(process.uptime() * 1000);

在 Node.js 最新 LTS 版本 v10.16.0 上,在我們個(gè)人工作電腦上:

node console.js // 平均時(shí)間為 86ms time node console.js // node console.js 0.08s user 0.03s system 92% cpu 0.114 total

看起來(lái),在 100ms 的目標(biāo)下,留給后面代碼加載的時(shí)間不多了。。。

在來(lái)看看目前函數(shù)平臺(tái)提供的容器里的執(zhí)行情況:

node console.js // 平均時(shí)間在 170ms time node console.js // real 0m0.177s // user 0m0.051s // sys 0m0.009s

Emmm… 情況看起來(lái)更糟了。

我們?cè)谝胍粋€(gè)模塊看看,以 serverless-runtime 為例(例二):

// require.js console.time('load'); require('serverless-runtime'); console.timeEnd('load');

本地環(huán)境:

node reuqire.js // 平均耗時(shí) 329ms

服務(wù)器環(huán)境:

node require.js // 平均耗時(shí) 1433ms

我枯了。。。
這樣看來(lái),從 Node.js 本身加載完,然后加載一個(gè)函數(shù)運(yùn)行時(shí),就要耗時(shí) 1700ms。
看來(lái) Node.js 本身并沒(méi)有那么快,我們 100ms 的目標(biāo)看起來(lái)很困難啊!

為什么這么慢

為什么會(huì)運(yùn)行的這么慢?而且兩個(gè)環(huán)境差異這么大?我們需要對(duì)整個(gè)運(yùn)行過(guò)程進(jìn)行分析,找到耗時(shí)比較高的點(diǎn),這里我們使用 Node.js 本身自帶的 profile 工具。

node --prof require.js node --prof-process isolate-xxx-v8.log > result [Summary]: ticks total nonlib name60 13.7% 13.8% JavaScript371 84.7% 85.5% C++10 2.3% 2.3% GC4 0.9% Shared libraries3 0.7% Unaccounted [C++]: ticks total nonlib name198 45.2% 45.6% node::contextify::ContextifyScript::New(v8::FunctionCallbackInfo<v8::Value> const&)13 3.0% 3.0% node::fs::InternalModuleStat(v8::FunctionCallbackInfo<v8::Value> const&)8 1.8% 1.8% void node::Buffer::(anonymous namespace)::StringSlice<(node::encoding)1>(v8::FunctionCallbackInfo<v8::V alue> const&)5 1.1% 1.2% node::GetBinding(v8::FunctionCallbackInfo<v8::Value> const&)4 0.9% 0.9% __memmove_ssse3_back4 0.9% 0.9% __GI_mprotect3 0.7% 0.7% v8::internal::StringTable::LookupStringIfExists_NoAllocate(v8::internal::String*)3 0.7% 0.7% v8::internal::Scavenger::ScavengeObject(v8::internal::HeapObjectReference**, v8::internal::HeapObject*)3 0.7% 0.7% node::fs::Open(v8::FunctionCallbackInfo<v8::Value> const&)

對(duì)運(yùn)行時(shí)啟動(dòng)做同樣的操作

[Summary]: ticks total nonlib name236 11.7% 12.0% JavaScript1701 84.5% 86.6% C++35 1.7% 1.8% GC47 2.3% Shared libraries28 1.4% Unaccounted [C++]: ticks total nonlib name453 22.5% 23.1% t node::fs::Open(v8::FunctionCallbackInfo<v8::Value> const&)319 15.9% 16.2% T node::contextify::ContextifyContext::CompileFunction(v8::FunctionCallbackInfo<v8::Value> const&)93 4.6% 4.7% t node::fs::InternalModuleReadJSON(v8::FunctionCallbackInfo<v8::Value> const&)84 4.2% 4.3% t node::fs::Read(v8::FunctionCallbackInfo<v8::Value> const&)74 3.7% 3.8% T node::contextify::ContextifyScript::New(v8::FunctionCallbackInfo<v8::Value> const&)45 2.2% 2.3% t node::fs::InternalModuleStat(v8::FunctionCallbackInfo<v8::Value> const&)...

可以看到,整個(gè)過(guò)程主要耗時(shí)是在 C++ 層面,相應(yīng)的操作主要為 Open、ContextifyContext、CompileFunction。這些調(diào)用通常是出現(xiàn)在 require 操作中,主要覆蓋的內(nèi)容是模塊查找,加載文件,編譯內(nèi)容到 context 等。

看來(lái),require 是我們可以?xún)?yōu)化的第一個(gè)點(diǎn)。

如何更快

從上面得知,主要影響我們啟動(dòng)速度的是兩個(gè)點(diǎn),文件 I/O 和代碼編譯。我們分別來(lái)看如何優(yōu)化。

? 文件 I/O

整個(gè)加載過(guò)程中,能夠產(chǎn)生文件 I/O 的有兩個(gè)操作:

一、查找模塊

因?yàn)?Node.js 的模塊查找其實(shí)是一個(gè)嗅探文件在指定目錄列表里是否存在的過(guò)程,這其中會(huì)因?yàn)榕袛辔募娌淮嬖?#xff0c;產(chǎn)生大量的 Open 操作,在模塊依賴(lài)比較復(fù)雜的場(chǎng)景,這個(gè)開(kāi)銷(xiāo)會(huì)比較大。

二、讀取模塊內(nèi)容

找到模塊后,需要讀取其中的內(nèi)容,然后進(jìn)入之后的編譯過(guò)程,如果文件內(nèi)容比較多,這個(gè)過(guò)程也會(huì)比較慢。

那么,如何能夠減少這些操作呢?既然模塊依賴(lài)會(huì)產(chǎn)生很多 I/O 操作,那把模塊扁平化,像前端代碼一樣,變成一個(gè)文件,是否可以加快速度呢?

說(shuō)干就干,我們找到了社區(qū)中一個(gè)比較好的工具 ncc,我們把 serverless-runtime 這個(gè)模塊打包一次,看看效果。

服務(wù)器環(huán)境:

ncc build node_modules/serverless-runtime/src/index.ts node require.js // 平均加載時(shí)間 934ms

看起來(lái)效果不錯(cuò),大概提升了 34% 左右的速度。

但是,ncc 就沒(méi)有問(wèn)題嘛?我們寫(xiě)了如下的函數(shù):

import * as _ from 'lodash'; import * as Sequelize from 'sequelize'; import * as Pandorajs from 'pandora'; console.log('lodash: ', _); console.log('Sequelize: ', Sequelize); console.log('Pandorajs: ', Pandorajs);

測(cè)試了啟用 ncc 前后的差異:

可以看到,ncc 之后啟動(dòng)時(shí)間反而變大了。這種情況,是因?yàn)樘嗟哪K打包到一個(gè)文件中,導(dǎo)致文件體積變大,整體加載時(shí)間延長(zhǎng)。可見(jiàn),在使用 ncc 時(shí),我們還需要考慮 tree-shaking 的問(wèn)題。

? 代碼編譯

我們可以看到,除了文件 I/O 外,另一個(gè)耗時(shí)的操作就是把 Javascript 代碼編譯成 v8 的字節(jié)碼用來(lái)執(zhí)行。我們的很多模塊,是公用的,并不是動(dòng)態(tài)變化的,那么為什么每次都要編譯呢?能不能編譯好了之后,以后直接使用呢?

這個(gè)問(wèn)題,V8 在 2015 年已經(jīng)替我們想到了,在 Node.js v5.7.0 版本中,這個(gè)能力通過(guò) VM.Script 的 cachedData暴露了出來(lái)。而且,這些 cache 是跟 V8 版本相關(guān)的,所以一次編譯,可以在多次分發(fā)。

我們先來(lái)看下效果:

//使用 v8-compile-cache 在本地獲得 cache,然后部署到服務(wù)器上 node require.js // 平均耗時(shí) 868ms

大概有 40% 的速度提升,看起來(lái)是一個(gè)不錯(cuò)的工具。

但它也不夠完美,在加載 code cache 后,所有的模塊加載不需要編譯,但是還是會(huì)有模塊查找所產(chǎn)生的文件 I/O 操作。

? 黑科技

如果我們把 require 函數(shù)做下修改,因?yàn)槲覀冊(cè)诤瘮?shù)加載過(guò)程中,所有的模塊都是已知已經(jīng) cache 過(guò)的,那么我們可以直接通過(guò) cache 文件加載模塊,不用在查找模塊是否存在,就可以通過(guò)一次文件 I/O 完成所有的模塊加載,看起來(lái)是很理想的。

不過(guò),可能對(duì)遠(yuǎn)程調(diào)試等場(chǎng)景不夠優(yōu)化,源碼索引上會(huì)有問(wèn)題。這個(gè),之后會(huì)做進(jìn)一步嘗試。

近期計(jì)劃

有了上面的一些理論驗(yàn)證,我們準(zhǔn)備在生產(chǎn)環(huán)境中將上述優(yōu)化點(diǎn),如:ncc、code cache,甚至 require 的黑科技,付諸實(shí)踐,探索在加載速度,用戶(hù)體驗(yàn)上的平衡點(diǎn),以取得速度上的提升。

其次,會(huì) review 整個(gè)函數(shù)運(yùn)行時(shí)的設(shè)計(jì)及業(yè)務(wù)邏輯,減少因?yàn)檫壿嫴缓侠韺?dǎo)致的耗時(shí),合理的業(yè)務(wù)邏輯,才能保證業(yè)務(wù)的高效運(yùn)行。

最后,Node.js 12 版本對(duì)內(nèi)部的模塊默認(rèn)做了 code cache,對(duì) Node.js 默認(rèn)進(jìn)程的啟動(dòng)速度提升比較明顯,在服務(wù)器環(huán)境中,可以控制在 120ms 左右,也可以考慮引用嘗試下。

未來(lái)思考

其實(shí),V8 本身還提供了像 Snapshot 這樣的能力,來(lái)加快本身的加載速度,這個(gè)方案在 Node.js 桌面開(kāi)發(fā)中已經(jīng)有所實(shí)踐,比如 NW.js、Electron 等,一方面能夠保護(hù)源碼不泄露,一方面還能加快進(jìn)程啟動(dòng)速度。Node.js 12.6 的版本,也開(kāi)啟了 Node.js 進(jìn)程本身的在 user code 加載前的 Snapshot 能力,但目前看起來(lái)啟動(dòng)速度提升不是很理想,在 10% ~ 15% 左右。我們可以嘗試將函數(shù)運(yùn)行時(shí)以 Snapshot 的形式打包到 Node.js 中交付,不過(guò)效果我們暫時(shí)還沒(méi)有定論,現(xiàn)階段先著手于比較容易取得成果的方案,硬骨頭后面在啃。

另外,Java 的函數(shù)計(jì)算在考慮使用 GraalVM 這樣方案,來(lái)加快啟動(dòng)速度,可以做到 10ms 級(jí),不過(guò)會(huì)失去一些語(yǔ)言上的特性。這個(gè)也是我們后續(xù)的一個(gè)研究方向,將函數(shù)運(yùn)行時(shí)整體編譯成 LLVM IR,最終轉(zhuǎn)換成 native 代碼運(yùn)行。不過(guò)又是另一塊難啃的骨頭。


原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

總結(jié)

以上是生活随笔為你收集整理的如何加快 Node.js 应用的启动速度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美日韩免费在线视频 | 91久| 97se在线| 欧美午夜精品久久久久久孕妇 | 国产精品后入内射日本在线观看 | 国产福利短视频 | 亚洲一区二区三区久久久 | 国产人成视频在线观看 | 亚洲在线不卡 | 特级做a爱片免费69 少妇第一次交换又紧又爽 亚洲大胆人体 | 一吻定情2013日剧 | 国产剧情一区二区 | 国产精品美女毛片真酒店 | 国产免费毛卡片 | 国产99久久九九精品无码 | 成人a免费 | 婷婷五月综合激情 | 国产精品999久久久 在线青草 | 人妻少妇一区 | 97桃色| 国产高清av | 国产无| 色婷婷一区二区三区 | 嫩草影院在线观看视频 | 国产免费高清 | 一级做a爱视频 | 国产亚洲成av人在线观看导航 | 一级黄色网 | 国产视频九色蝌蚪 | 免费一级特黄特色大片 | av网站在线观看免费 | 一级黄色短片 | 亚洲精品aⅴ | 亚洲无套| 中文字幕黄色片 | 超碰在线个人 | 黄色av网址在线 | 一本大道久久 | 精品一性一色一乱农村 | www..com黄色 | 最新国产精品自拍 | 最新中文字幕一区 | 国产精品精 | avtt在线播放 | 成人资源在线观看 | 亚洲av久久久噜噜噜噜 | 尤物视频在线免费观看 | 亚洲自拍第三页 | 久久国色 | 免费成人av在线播放 | 国产真实生活伦对白 | 成人欧美视频 | 日本亚洲欧美在线 | 亚洲成色在线 | 三上悠亚痴汉电车 | 中文在线不卡 | 又色又爽又黄18网站 | 91视频导航 | 国内av自拍 | 黄色三级a | 亚洲成人动漫在线观看 | 操日本女人 | 毛片视频免费观看 | 日本视频一区二区三区 | 一级v片| 法国极品成人h版 | 一区在线看| 天天看黄色 | 亚洲视频国产视频 | 天天操夜操 | 久久精品6 | 国产熟女一区二区三区四区 | 中文精品久久 | 国产午夜精品免费一区二区三区视频 | 国产一区二区视频免费在线观看 | 大桥未久视频在线观看 | 日韩avav | 欧美精品国产一区二区 | 五月天婷婷在线观看 | 理论片中文字幕 | 日日夜夜2017 | aaa大片十八岁禁止 中文字幕亚洲在线观看 | 国产精品资源网站 | 羞羞羞网站 | 国产一区在线不卡 | 黄色美女毛片 | 日日狠狠久久偷偷四色综合免费 | 欧美性视屏| 在线尤物| 欧美视频亚洲 | 黄色动漫免费在线观看 | 99久久久久无码国产精品 | 神马福利视频 | 国产不卡一区 | 肥臀浪妇太爽了快点再快点 | 婷婷亚洲精品 | 人妻一区二区三区 | 国产91小视频 | 色欲色香天天天综合网www |