当前位置: 首页 > 后端技术 > Node.js

使用V8和nodeeasyprofile分析nodejs应用

时间:2023-04-03 12:29:19 Node.js

介绍我们使用nodejs写好程序后,如果要分析程序的性能,就需要用到profile工具。虽然第三方的profile工具很多,方便又强大,这里主要讲解V8和node自带的profile,因为它们足够简单,功能也足够强大。使用它们基本可以满足我们日常的分析需求。下面一起来看看吧。使用V8内置的profiler工具nodejs运行在V8引擎上,V8引擎本身提供了一个内置的profile工具。要直接使用V8引擎,我需要下载V8源代码然后构建它。一般来说,我们有两种构建V8的方法。使用gm构建V8gm是一个非常方便的一体化脚本,可用于生成构建文件、触发构建过程和运行测试用例。一般来说,gm脚本的位置是:/path/to/v8/tools/dev/gm.py我们可以为它创建一个别名以备后用:aliasgm=/path/to/v8/tools/dev/gm.pybuildV8:gmx64.release构建后用例验证:gmx64.release.check是不是很简单?手动构建V8手动构建V8比较麻烦,我们也可以分为三步,1.生成构建文件,2.触发构建,3.运行测试用例我们可以使用gn为out/foo生成构建文件:gnargsout/foo上面的命令将打开一个编辑窗口,用于输入gn的参数。我们可以添加一个列表来查看所有的参数说明:gnargsout/foo--list当然我们也可以直接指定参数来创建构建文件:gngenout/foo--args='is_debug=falsetarget_cpu="x64"v8_target_cpu="arm64"use_goma=true'除了gn,我们还可以使用v8自带的v8gen创建构建文件:aliasv8gen=/path/to/v8/tools/dev/v8gen.pyv8gen-b'V8Linux64-debugbuilder'-mclient.v8foo创建构建文件后,我们可以编译它。构建所有V8:ninja-Cout/x64.releaseonlybuildd8:ninja-Cout/x64.released8最后我们运行测试以验证构建是否成功:tools/run-tests.py--outdirout/foo//ortools/run-tests.py--gngenerateprofilefile构建V8后,我们可以使用其中的命令来生成profile文件。找到d8文件:d8--profapp.js通过添加--prof参数,我们可以生成一个v8.log文件,其中包含分析数据。注意,此时的v8.log文件虽然不是二进制格式,但仍然难以阅读,因为它只是简单的进行日志操作,并没有进行有效的统计分析。让我们看看生成的文件:...profiler,begin,1000tick,0x7fff688bbe36,839,0,0x0,6tick,0x7fff688bc2d2,2081,0,0x0,6tick,0x100373430,3263,0,0x0,6code-creation,Builtin,3,3746,0x1008aa020,1634,RecordWritecode-creation,Builtin,3,3766,0x1008aa6a0,457,EphemeronKeyBarriercode-creation,Builtin,3,3773,0x1008aa880,44,AdaptorWithBuiltinExitFramecode-creation,4780a,gurampolinetinaptorcreationd,9,3Arta,3,3788,0x1008aaa00,203,CallFunction_ReceiverIsNullOrUndefinedcode-creation,Builtin,3,3796,0x1008aaae0,260,CallFunction_ReceiverIsNotNullOrUndefinedcode-creation,Builtin,3,3804,0x1008aac00,285,CallFunction_ReceiverIsAnycode-creation,Builtin,3,3811,0x1008aad20,130,CallBoundFunction...可以看出日志文件中只记录了事件的发生,并没有统计信息。分析生成的文件如果想生成我们可以理解的统计信息,可以使用://windowstools\windows-tick-processor.batv8.log//linuxtools/linux-tick-processorv8.log//macOStools/mac-tick-processorv8.log生成可理解的日志文件。生成的文件如下所示:Statisticalprofilingresultfrombenchmarks\v8.log,(4192ticks,0unaccounted,0excluded)。[共享库]:勾选总非库名称90.2%0.0%C:\WINDOWS\system32\ntdll.dll20.0%0.0%C:\WINDOWS\system32\kernel32.dll[JavaScript]:勾选总非库名称74117.7%17.7%LazyCompile:am3crypto.js:1081132.7%2.7%LazyCompile:Scheduler.schedulerichards.js:1881032.5%2.5%LazyCompile:rewrite_nboyerearley-boyer.js:36041032.5%2.5%LazyCompile:TaskControlBlock.runrichards.js:324962.3%2.3%Builtin:JSConstructCall...with用惯了IDE的同学可能会想,能不能有一个网页统一显示这个结果呢?是的,V8提供了profview工具,可以让我们从webUI分析生成的结果。profview是一个html工具,我们可以从https://chromium.googlesource下载...如果要使用profview,我们还需要对第一步生成的v8.log文件进行预处理:linux-tick-processor--preprocess>v8.json然后在profview页面上传v8.json进行分析。生成时间线图--prof还可以接收其他参数,比如--log-timer-events,通过使用这个参数可以用来统计在V8引擎中花费的时间。d8--prof--log-timer-eventsapp.jstools/plot-timer-eventsv8.log第一条命令生成一个v8.log文件,第二条命令生成一个timer-events.png图形文件,比较直观显示数据。因为生成日志其实对程序的性能有一定的影响,我们也可以在plot-timer-events中加入失真因子来修正这个问题。如果我们不指定校正因子,脚本会自动查找。当然我们也可以手动指定如下:tools/plot-timer-events--distortion=4500v8.log使用nodejs的profile工具nodejs4.4.0之前只能下载V8的源码编译正在进行的简介。nodejs4.4.0之后,node命令集成了V8的功能。我们可以使用node--v8-options来查看node中可用的V8参数:node--v8-optionsSSE3=1SSSE3=1SSE4_1=1SAHF=1AVX=1FMA3=1BMI1=1BMI2=1LZCNT=1POPCNT=1ATOM=0概要:shell[options][--shell][...]d8[options][-e][--shell][[--module]。..]-e在V8中执行字符串--shell运行交互式JavaScriptshell--module将文件作为JavaScript模块执行('-'和'--'都可以):--flag(仅限bool标志)--no-flag(仅限bool标志)--flag=value(仅限非bool标志,'='周围没有空格)--flagvalue(non-boolflagsonly)--(capturesallremainingargsinJavaScript)Options:--use-strict(enforcestrictmode)type:booldefault:false--es-staging(enabletest-worthyharmonyfeatures(forinternaluseonly))type:booldefault:false...参数很多,相同的我们可以使用使用--prof参数:node--profapp.js会在本地目录下生成类似isolate-0x102884000-14025-v8.log的文件。文件内容与V8生成的一致,这里不再一一列举。分析这个文件,可以使用:node--prof-processisolate-0x102884000-14025-v8.log>processed.txt查看生成的分析结果:Statisticalprofilingresultfromisolate-0x102884000-14025-v8.log,(296笔报价,4笔下落不明,0笔排除)。[共享库]:勾选总非库名称62.0%/usr/lib/system/libsystem_pthread.dylib62.0%/usr/lib/system/libsystem_kernel.dylib20.7%/usr/lib/system/libsystem_malloc.dylib10.3%/usr/lib/system/libmacho.dylib10.3%/usr/lib/system/libcorecrypto.dylib[JavaScript]:勾选总非库名称...[摘要]:勾选总非库名称00.0%0.0%JavaScript27693.2%98.6%C++248.1%8.6%GC165.4%共享库41.4%未说明[C++入口点]:tickscpp总名称14263.1%48.0%T__ZN2v88internal21Builtin_HandleApiCallEiPmPNS0_7IsolateE8236.4%27.7%T__ZN2v88internal40Builtin_CallSitePrototypeGetPromiseIndexEiPmPNS0_7IsolateE10.4%0.3%T__ZN2v88internal40Builtin_CallSitePrototypeGetFileNameEiPmPNS0_7IsolateE...和V8也很像。从总结和每个入口点,我们可以进一步分析哪个程序占用了更多的CPU时间。上面的100%意味着93.2%的采样数据都在运行C++代码。那么我们应该看看哪些C++代码占用时间最多,找出相应的解决方案。本文作者:flydean程序的那些事本文链接:http://www.flydean.com/nodejs-profile/本文来源:flydean的博客欢迎关注我的公众号:《程序那些事儿》最通俗的解读,最深刻的干货,最简洁的教程,还有很多你不知道的小技巧等你来发现!