如何排查 Electron V8 引发的内存 OOM 问题(中)

简介: 如何排查 Electron V8 引发的内存 OOM 问题(中)

更多精彩内容,欢迎观看:

如何排查 Electron V8 引发的内存 OOM 问题(上):https://developer.aliyun.com/article/1263250?spm=a2c6h.13148508.setting.14.1e7f4f0e2Cy18t


如何通过编译 Electron 源码提升 v8 堆内存上限


为了突破 v8 堆内存上限,我们需要重新编译 Electron 源码,下面会详细介绍如何编译出一个提升 v8 堆内存上限的 Electron 版本。


▐  构建前配置科学上网环境


首先需要确保电脑系统具备如下环境:

  1. 科学上网环境
  2. Visual Studio 2019 版本(推荐版本)
  3. Node.js(建议使用最新稳定版本)
  4. Git(建议使用最新稳定版本)
  5. Python3(推荐版本)
  6. Debugging Tools for Windows of Windows SDK(根据电脑系统的实际情况确定使用哪个版本)
  7. 卸载 nvm 工具(如果有安装的话)
  8. 至少 25 GB 的磁盘空间剩余


准备好这些环境后,接着通过 git 命令下载谷歌提供的 depot_tools 工具:


> git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git


我们也可以通过谷歌提供的下载地址下载该工具,下载完成后把压缩包解压到 D:\depot_tools 目录(具体路径可以自行设置),确保该目录下存在 .git 子目录和 gclient.bat 批处理文件才行。


然后在系统环境变量中增加 depot_tools 的目录路径(注意这个路径必须在所有其他环境变量之前),如下图所示:



接着再增加下面 5 个系统环境变量:


DEPOT_TOOLS_WIN_TOOLCHAIN: 0DEPOT_TOOLS_DIR: D:\depot_toolsGIT_CACHE_PATH: D:\.gitCachehttp_proxy: http://127.0.0.1:13658https_proxy: http://127.0.0.1:13658


  1. DEPOT_TOOLS_WIN_TOOLCHAIN:使 depot_tools 工具不下载 Visual Studio 工具链(否则 depot_tools 将会下载一个只有谷歌内部员工才有权限使用的 Visual Studio,做此设置的前提是需要自己安装好 Visual Studio 开发工具)。
  2. GIT_CACHE_PATH:设置 git 的缓存目录,由于构建过程中需要下载大约 10 GB 的源码及资源文件,因此要防备网络断开、下载失败等情况,如果团队中其他成员也需要构建 Electron,那可以考虑共享 git 的缓存目录来提升构建效率。
  3. http_proxy / https_proxy:为 Python 提供科学上网的支持。


最后还需要为一系列的工具配置科学上网的环境:


控制台输入下面指令设置 git 的科学上网环境,注意端口号以电脑系统配置的代理端口号为准。



> git config --global https.proxy http://127.0.0.1:13658> git config --global http.proxy http://127.0.0.1:13658


控制台输入下面指令设置 node.js 的科学上网的环境,注意端口号以电脑系统配置的代理端口号为准。


> npm config set proxy=http://127.0.0.1:13658> npm config set https-proxy http://127.0.0.1:13658


控制台输入下面指令设置 gclient 的代理,注意端口号以电脑系统配置的代理端口号为准。


> set http_proxy=http://127.0.0.1:13658> set https_proxy=http://127.0.0.1:13658


控制台输入下面指令设置 winhttp 的代理,注意端口号以电脑系统配置的代理端口号为准。


> C:\Windows\system32>netsh> netsh>winhttp> netsh winhttp>> netsh winhttp>set proxy http://127.0.0.1:13658



▐  构建不同版本的 Electron


当构建依赖的工具都配置好科学上网的环境后,就可以开始构建 Electron 源码了。接下来会分别介绍如何构建 nightly、release、debug、突破 V8 堆内存上限等不同版本的 Electron。


  • 构建 nightly 版本的 Electron


首先创建一个目录,然后在该路径下用管理员的身份启动命令行工具 cmd.exe(不能使用 PowerShell、cygwin、Git Bash 等工具) 执行下面 3 个指令,用来初始化编译环境并同步 Chromium、Electron 和 node.js 的代码及其相关依赖。


> gclient config --name "src/electron" --unmanaged https://github.com/electron/electron> gclient sync --with_branch_heads --with_tags> gclient sync -f


因为 gclient 要下载 Chromium、Electron、node.js 等源码及资源文件与构建工具,所以这个过程非常漫长,请耐心等待。如果执行 "gclient sync --with_branch_heads --with_tags" 指令时遇到了下载 dugite(用于构建 Git 版本的工具)失败的问题,可以自行下载压缩包后放在当前目录下,然后再重新执行上述指令。



Downloading Git from: https://github.com/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gzError raised while downloading https://github.com/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz GotError [RequestError]: read ECONNRESET    at ClientRequest.<anonymous> (D:\workspace\electron\src\electron\node_modules\dugite\node_modules\got\source\request-as-event-emitter.js:178:14)    at Object.onceWrapper (node:events:628:26)    at ClientRequest.emit (node:events:525:35)    at ClientRequest.origin.emit (D:\workspace\electron\src\electron\node_modules\dugite\node_modules\@szmarczak\http-timer\source\index.js:37:11)    at TLSSocket.socketErrorListener (node:_http_client:481:9)    at TLSSocket.emit (node:events:513:28)    at emitErrorNT (node:internal/streams/destroy:157:8)    at emitErrorCloseNT (node:internal/streams/destroy:122:3)    at processTicksAndRejections (node:internal/process/task_queues:83:21) {  code: 'ECONNRESET',  host: 'github.com',  hostname: 'github.com',  method: 'GET',  path: '/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz',  socketPath: undefined,  protocol: 'https:',  url: 'https://github.com/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz',  gotOptions: {    path: '/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz',    protocol: 'https:',    slashes: true,    auth: null,    host: 'github.com',    port: null,    hostname: 'github.com',    hash: null,    search: null,    query: null,    pathname: '/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz',    href: 'https://github.com/desktop/dugite-native/releases/download/v2.29.3-2/dugite-native-v2.29.3-3d467be-windows-x64.tar.gz',    retry: {      retries: [Function (anonymous)],      methods: [Set],      statusCodes: [Set],      errorCodes: [Set]    },    headers: {      'user-agent': 'dugite',      accept: 'application/octet-stream',      'accept-encoding': 'gzip, deflate'    },    hooks: {      beforeRequest: [],      beforeRedirect: [],      beforeRetry: [],      afterResponse: [],      beforeError: [],      init: []    },    decompress: true,    throwHttpErrors: true,    followRedirect: true,    stream: true,    form: false,    json: false,    cache: false,    useElectronNet: false,    secureProtocol: 'TLSv1_2_method',    method: 'GET'  }}


等控制台输出下面的结果后,表明上述指令已执行完成。


Operation completed over 1 objects/69.2 MiB.Hook 'python3 src/tools/update_pgo_profiles.py --target=win32 update --gs-url-base=chromium-optimization-profiles/pgo_profiles' took 20.10 secsRunning hooks:  62% (86/137) Fetch PGO profiles for win64________ running 'python3 src/tools/update_pgo_profiles.py --target=win64 update --gs-url-base=chromium-optimization-profiles/pgo_profiles' in 'D:\workspace\electron'Copying gs://chromium-optimization-profiles/pgo_profiles/chrome-win64-main-1672768604-8da543c818b6aea3eae2ad5cb80cfe61abd454a1.profdata...Downloading to temp gzip filename D:\workspace\electron\src\chrome\build\pgo_profiles\chrome-win64-main-1672768604-8da543c818b6aea3eae2ad5cb80cfe61abd454a1.profdata_.gztmpUncompressing temporarily gzipped file to D:\workspace\electron\src\chrome\build\pgo_profiles\chrome-win64-main-1672768604-8da543c818b6aea3eae2ad5cb80cfe61abd454a1.profdata...\ [1 files][ 68.5 MiB/ 68.5 MiB]    7.2 MiB/sOperation completed over 1 objects/68.5 MiB.Hook 'python3 src/tools/update_pgo_profiles.py --target=win64 update --gs-url-base=chromium-optimization-profiles/pgo_profiles' took 21.92 secsRunning hooks:  67% (93/137) style_perftest_files________ running 'python3 src/third_party/depot_tools/download_from_google_storage.py --no_auth --quiet --bucket chromium-style-perftest -d src/third_party/blink/renderer/core/css/perftest_data' in 'D:\workspace\electron'NOTICE: You have PROXY values set in your environment, but gsutilin depot_tools does not (yet) obey them.Also, --no_auth prevents the normal BOTO_CONFIG environmentvariable from being used.To use a proxy in this situation, please supply those settingsin a .boto file pointed to by the NO_AUTH_BOTO_CONFIG environmentvariable.Hook 'python3 src/third_party/depot_tools/download_from_google_storage.py --no_auth --quiet --bucket chromium-style-perftest -d src/third_party/blink/renderer/core/css/perftest_data' took 81.51 secsRunning hooks: 100% (137/137), done.


接着再执行下面的指令,此时会在 src/out/Testing(Testing 名称可以更改,但 src/out 子目录不能更改) 子目录内生成一个测试配置文件夹,然后我们会使用这个文件夹下的 testing.gn 构建脚本来构建 Electron 源码。


> cd src> set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools> gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"


如果执行上述指令时遇到下面报错信息,可以直接看解决方法。


若 gn 没找到 src/buildtools 的路径,则解决方法如下:

  1. 检查环境变量 CHROMIUM_BUILDTOOLS_PATH 的值是否为 src 目录下 buildtools 的路径。
  2. 在 src 的上一级目录保留 .gclient 和 .gclient_entries 文件。


gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"gn.py: Could not find checkout in any parent of the current path.This must be run inside a checkout.


若安装的 Windows 10 SDK 版本不匹配,解决方法如下:


Traceback (most recent call last):  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 315, in <module>    main()  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 273, in main    env = _LoadToolchainEnv(cpu, toolchain_root, win_sdk_path, target_store)  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 189, in _LoadToolchainEnv    return _ExtractImportantEnvironment(variables)  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 67, in _ExtractImportantEnvironment    raise Exception(Exception: Path "C:\Program Files (x86)\Windows Kits\10\include\10.0.20348.0\shared" from environment variable "include" does not exist. Make sure the necessary SDK is installed.ERROR at //build/toolchain/win/toolchain.gni:500:24: Script returned non-zero exit code.  win_toolchain_data = exec_script("//build/toolchain/win/setup_toolchain.py",                       ^----------Current dir: D:/workspace/electron/src/out/Testing/Command: D:/workspace/depot_tools/bootstrap-2@3_8_10_chromium_26_bin/python3/bin/python3.exe D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" "C:\Program Files (x86)\Windows Kits\10" "C:\Windows\System32;C:\Windows\SysWOW64;Arm64Unused" win x86 environment.x86Returned 1.See //build/toolchain/win/BUILD.gn:34:3: whence it was called.  win_toolchains("x86") {  ^----------------------See //BUILD.gn:83:1: which caused the file to be included.group("gn_all") {


首先打开 Visual Studio Installer(该工具跟 Visual Studio 一起安装),然后点击“修改”按钮,如下图所示:



接着选择单个组件,把报错信息中提示要安装的 Windows 10 SDK(注意版本号)勾选上并点击“修改”按钮进行安装:



由于 Visual Studio Installer 安装的 Windows 10 SDK 不包含 Debugging Tools for Windows,所以安装完成后还不能继续执行指令 。我们还要打开系统设置中的“应用和功能”选项并找到刚刚安装的 Windows 10 SDK,点击“修改”按钮后在弹出界面中选择 Change 选项并点击 Next 按钮,选中 Debugging Tools for Windows,然后点击 Change 按钮。



若报了 "AssertionError: user32.lib is not found in LIB" 的错误,则解决方法如下:


Traceback (most recent call last):  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 314, in <module>    main()  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 274, in main    vc_lib_um_path = FindFileInEnvList(env, 'LIB', ';', 'user32.lib')  File "D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py", line 212, in FindFileInEnvList    assert optional, "%s is not found in %s:\n%s\nCheck if it is installed." % (AssertionError: user32.lib is not found in LIB:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\ATLMFC\lib\x64C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\lib\x64C:\Program Files (x86)\Windows Kits\10\lib\10.0.20348.0\ucrt\x64C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64Check if it is installed.ERROR at //build/config/win/BUILD.gn:310:27: Script returned non-zero exit code.  vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py",                          ^----------Current dir: D:/workspace/electron/src/out/Release/Command: D:/workspace/depot_tools/bootstrap-2@3_8_10_chromium_26_bin/python3/bin/python3.exe D:/workspace/electron/src/build/toolchain/win/setup_toolchain.py "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" "C:\Program Files (x86)\Windows Kits\10" "C:\Windows\System32;C:\Windows\SysWOW64;Arm64Unused" win x64 noneReturned 1.See //build/config/BUILDCONFIG.gn:437:35: which caused the file to be included.  default_executable_configs += [ "//build/config/win:cfi_linker" ]


把 src\build\toolchain\win\setup_toolchain.py 第178 行的 Windows 10 SDK 版本 "10.019041.0" 修改为我们刚刚安装的 "10.0.20348.0" 版本即可。



经过这些步骤修改完成后,就可以继续执行上述指令了。执行成功后再执行下面的指令就开始正式构建 Electron 源码,由于这个指令要编译链接 4 万多个文件,因此会花费更长的时间。建议可以在睡觉前跑该指令,等第二天醒来就可以在 src/out/Testing 目录下找到我们自己编译生成的 electron.exe 可执行程序及相关的二进制资源了。



> ninja -C out/Testing electron -j 4



  • 构建 release 版本的 Electron


在上一章节中,我们使用 build/args/testing.gn 脚本构建了 Electron 源码,然后在 src/out/Testing 目录下就会生成非常多的 dll、lib、exe 等文件。由于 Chromium 项目极其庞大,编译、链接工作往往需要耗费大量的时间,于是 Chromium 引入了分块构建的技术,将每个模块作为单独的动态库进行构建,这样就能大大加快编译、链接的速度。


我们除了可以使用 build/args/testing.gn 构建 Electron 源码外,还可以使用 build/args/release.gn 脚本构建 release 版本的 Electron。通过下面指令编译、链接 Electron 源码后,src\out\Release 目录下就会输出 release 版本的 Electron 编译结果。


> cd src> set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools> gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"> ninja -C out/Release electron -j 4


默认情况下,在编译前 gclient 获取的是 nightly 分支的 Electron 源码,获取源码的指令如下:

> gclient config --name "src/electron" --unmanaged https://github.com/electron/electron> gclient sync --with_branch_heads --with_tags


这是 Electron 开发团队日常工作时使用的分支,而我们一般需要 main 分支或 18-x-y 这种具体某个版本的分支,因此需要通过下面 git 命令来切换 src/electron 目录下的分支:


切换 main 分支


> cd src/electron> git remote remove origin> git remote add origin https://github.com/electron/electron> git checkout main> git branch --set-upstream-to=origin/main> git pull


切换 18-x-y 分支


> cd src/electron> git remote remove origin> git remote add origin https://github.com/electron/electron> git checkout 18-x-y> git branch --set-upstream-to=origin/18-x-y> git pull


切换完 Electron 源码分支后,务必执行下面的命令拉取新 Electron 源码分支所依赖的 Chromium、node.js 等源码(gclient 会检查 src/electron 目录下的 DEPS 文件,从中获取依赖信息)。


> gclient sync -f


接着再使用 “ninja -C out\Release electron -j 4” 指令就可以编译我们期望的某个版本分支(如 18-x-y 分支)的 Electron 版本了。若编译过程遇到下面报错信息,可以直接看解决方法。


若报了 "To rebaseline" 的错误,可能与 XFG(eXtended Flow Guard:拓展控制流防护)有关,按照提示执行 copy 命令即可。


To rebaseline:  copy /y C:\Users\kelai\AppData\Local\Temp\tmpgx2zcmac\* D:\workspace\electron\src\third_party\win_build_output\midl\third_party\isimpledom\ISimpleDOMDocument.idl\x64ninja: build stopped: subcommand failed.


若报了 "error: use of undeclared identifier 'PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER'" 的错误,则打开 src\sandbox\win\src\startup_information_helper.cc 文件并注释掉 131 行的 if 语句块代码(不要注释 "expected_attributes--;" 这一行代码,否则处理属性时会出错)。


../../sandbox/win/src/startup_information_helper.cc(132,13): error: use of undeclared identifier 'PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER'            PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER, &component_filter_,            ^1 error generated.[7/24935] CXX obj/components/paint_preview/common/mojom/mojom/paint_preview_recorder.mojom.objninja: build stopped: subcommand failed.



若报了 "error: enumeration value 'D3D_FEATURE_LEVEL_12_2' not handled in switch [-Werror,-Wswitch]" 的错误,是因为 D3D_FEATURE_LEVEL_12_2 是在 10.0.20170.0 的 SDK 中才添加进来,需要做如下修改:

../../gpu/ipc/common/device_perf_info_mojom_traits.cc(16,11): error: enumeration value 'D3D_FEATURE_LEVEL_12_2' not handled in switch [-Werror,-Wswitch]  switch (d3d_feature_level) {          ^~~~~~~~~~~~~~~~~1 error generated.[939/19937] ACTION //third_party/blink/public/mojom:mojom_platform__generator(//build/toolchain/win:win_clang_x64)ninja: build stopped: subcommand failed.


首先打开 src\gpu\ipc\common\device_perf_info_mojom_traits.cc 文件在第 37 行添加下面代码:



接着打开 src\gpu\ipc\common\device_perf_info_mojom_traits.cc 文件在第 79 行添加下面代码:



最后打开 src\gpu\ipc\common\device_perf_info.mojom 文件在第 84 行添加下面代码:



若报了 "error: enumeration value 'AudioEffectType_FarFieldBeamForming' not handled in switch [-Werror,-Wswitch]" 的错误,则打开 src\media\audio\win\audio_low_latency_input_win.cc 文件第 195 行添加下面代码:


../../media/audio/win/audio_low_latency_input_win.cc(158,11): error: enumeration value 'AudioEffectType_FarFieldBeamForming' not handled in switch [-Werror,-Wswitch]  switch (type) {          ^~~~1 error generated.[2536/19159] CXX obj/media/formats/formats/dts_stream_parser.objninja: build stopped: subcommand failed.



若报了 "error: redefinition of '_DXVA_*_AV1'" 的错误,则打开 src\media\gpu\windows\d3d11_AV1_accelerator.cc 文件并删除两个 #pragma 及之间的所有内容:


../../media/gpu/windows/d3d11_av1_accelerator.cc(273,16): error: redefinition of '_DXVA_Tile_AV1'typedef struct _DXVA_Tile_AV1 {               ^C:\Program Files (x86)\Windows Kits\10\include\10.0.20348.0\um\dxva.h(1745,16): note: previous definition is heretypedef struct _DXVA_Tile_AV1 {               ^3 errors generated.[1274/16624] CXX obj/media/gpu/gpu/d3d11_h264_accelerator.objninja: build stopped: subcommand failed.



解决完编译过程遇到的上面几个问题后,继续编译直到控制台输出 "STAMP obj/electron/electron.stamp" 日志时才表明编译成功,并且也会在 src\out\Release 目录下生成很多无用的文件,如下图所示:



其实,我们只要按照 Electron 团队发布的文件(参照 node_modules\electron\dist 目录下的文件)从 src\out\Release 目录下挑选出来即可,最终分发给用户的也只是这些文件,其他文件都是不需要的。



接下来我们开始介绍如何构建突破 v8 堆内存上限的 Electron 版本。


  • 构建突破 v8 堆内存上限的 Electron 版本


早在 2014 年,Chrome 为了更好的安全性、稳定性和性能,就把 32 位进程切换为 64 位进程。但这样带来的副作用是每个指针从 4 个提升到 8 个字节,导致消耗了更多的内存。数据显示,在桌面端应用中 v8 占 Chrome 渲染器进程内存消耗的 60%。因此,v8 一直努力减少内存开销,在 v9.2 版本时通过将 64 位指针分为两半(其中高 32 位是基数,低 32 位是该基数的索引)来实现指针压缩,以尝试尽可能多地取回浪费的 4 个字节。


|----- 32 bits -----|----- 32 bits -----|Pointer:    |________base_______|_______index_______|


其中 v8 实现指针压缩的源码分析如下所示:


  1. 首先打开 src\third_party\electron_node\deps\v8\BUILD.gn 文件,默认 v8_enable_pointer_compression 和 v8_enable_pointer_compression_shared_cage 变量为空,若 v8_current_cpu 为 64位(arm64 是 arm 中 64 位体系结构,x64 是 x86 系列中的 64 位体系结构,如下图电脑是 x64)则 v8_enable_pointer_compression 和 v8_enable_pointer_compression_shared_cage 变量都被赋值为 true,然后 enabled_external_v8_defines 新增 V8_COMPRESS_POINTERS 的定义。
# Enable pointer compression (sets -dV8_COMPRESS_POINTERS).v8_enable_pointer_compression = ""v8_enable_pointer_compression_shared_cage = ""v8_enable_31bit_smis_on_64bit_arch = false
if (v8_enable_pointer_compression == "") {  v8_enable_pointer_compression =      v8_current_cpu == "arm64" || v8_current_cpu == "x64"}if (v8_enable_pointer_compression_shared_cage == "") {  v8_enable_pointer_compression_shared_cage = v8_enable_pointer_compression}
if (v8_enable_pointer_compression) {  enabled_external_v8_defines += [ "V8_COMPRESS_POINTERS" ]  if (v8_enable_pointer_compression_shared_cage) {    enabled_external_v8_defines += [ "V8_COMPRESS_POINTERS_IN_SHARED_CAGE" ]  } else {    enabled_external_v8_defines += [ "V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE" ]  }}if (v8_enable_pointer_compression || v8_enable_31bit_smis_on_64bit_arch) {  enabled_external_v8_defines += [ "V8_31BIT_SMIS_ON_64BIT_ARCH" ]}

  1. 接着打开 src\third_party\electron_node\deps\v8\include\v8-internal.h 文件,因为前面定义了 V8_COMPRESS_POINTERS,那么 kApiTaggedSize 就会等于 4个字节大小的 kApiInt32Size(否则等于系统指针大小,cpu x64 则为 8 个字节大小),这就是 v8 实现指针压缩的原理。
/** * Configuration of tagging scheme. */const int kApiSystemPointerSize = sizeof(void*);const int kApiDoubleSize = sizeof(double);const int kApiInt32Size = sizeof(int32_t);const int kApiInt64Size = sizeof(int64_t);
#ifdef V8_COMPRESS_POINTERSstatic_assert(    kApiSystemPointerSize == kApiInt64Size,    "Pointer compression can be enabled only for 64-bit architectures");const int kApiTaggedSize = kApiInt32Size;#elseconst int kApiTaggedSize = kApiSystemPointerSize;#endif



经过指针压缩后显著减少了内存消耗并提高了性能,但代价是 v8 将同一个进程中所有线程所使用的堆内存大小限制为 4GB。由于 Electron 对外发布版本默认打开了指针压缩,为了突破 v8 申请的堆内存上限,我们需要设置参数禁止指针压缩,并重新编译 Electron 版本,具体操作步骤如下:
首先打开 src\electron\build\args\all.gn 文件,添加下面的代码:


# Disable pointer compressionv8_enable_pointer_compression = falsev8_enable_pointer_compression_shared_cage = false


接着打开 src\third_party\electron_node\deps\v8\BUILD.gn 文件,把 v8_enable_pointer_compression 和 v8_enable_pointer_compression_shared_cage 变量都赋值为 false,关闭指针压缩功能。

最后在控制台执行下面指令重新编译 Electron 版本,等编译成功后 v8 就能突破 4GB 堆内存大小限制了。


> cd src> set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools> gn gen out/Release_disable_v8_pointer_compression --args="import(\"//electron/build/args/release.gn\")"> ninja -C out/Release_disable_v8_pointer_compression electron -j 4


默认情况下,64 位操作系统 v8 可以申请 8GB 堆内存。我们可以打印 performance.memory 看下 v8 堆内存最大可申请大小,如下所示:

▐  构建后清除代理设置


构建完成后,如果你想要清除掉前面为代理做的一系列设置,可以执行如下命令:


清除 git 代理:

> git config --global --unset http.proxy> git config --global --unset https.proxy


清除 npm 代理:


> npm config delete proxy> npm config delete https-proxy


清除 gclient 代理:

> set http_proxy=> set https_proxy=


清除系统代理:

> C:\Windows\system32>netsh> netsh>winhttp> netsh winhttp>> netsh winhttp>reset proxy


更多精彩内容,欢迎观看:

如何排查 Electron V8 引发的内存 OOM 问题(下):https://developer.aliyun.com/article/1263248?groupCode=taobaotech

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
2月前
|
监控 Java Linux
redisson内存泄漏问题排查
【9月更文挑战第22天】在排查 Redisson 内存泄漏问题时,首先需确认内存泄漏的存在,使用专业工具(如 JProfiler)分析内存使用情况,检查对象实例数量及引用关系。其次,检查 Redisson 使用方式,确保正确释放资源、避免长时间持有引用、检查订阅和监听器。此外,还需检查应用程序其他部分是否存在内存泄漏源或循环引用等问题,并考虑更新 Redisson 到最新版本以修复潜在问题。
|
3月前
|
JavaScript Java 开发工具
Electron V8排查问题之接近堆内存限制的处理如何解决
Electron V8排查问题之接近堆内存限制的处理如何解决
230 1
|
4月前
|
监控 安全 Java
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
121 2
|
3月前
|
搜索推荐 Java API
Electron V8排查问题之分析 node-memwatch 提供的堆内存差异信息来定位内存泄漏对象如何解决
Electron V8排查问题之分析 node-memwatch 提供的堆内存差异信息来定位内存泄漏对象如何解决
108 0
|
3月前
|
Web App开发 监控 Java
Electron V8排查问题之发现的内存泄漏问题如何解决
Electron V8排查问题之发现的内存泄漏问题如何解决
176 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
385 0
|
29天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
60 1
|
1月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
1月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
42 4