max_semi_space_size 设置值与实际值不一致的原因分析
问题由来
因为业务的需求,某 Node.js 性能平台用户需要调节新生代大小,Node.js 的启动参数里面的max_semi_space_size
可以设置新生代堆空间的大小。
node --v8-options | grep max_semi -A 3 -B 2--min_semi_space_size (min size of a semi-space (in MBytes), the new space consists of twosemi-spaces)type: int default: 0--max_semi_space_size (max size of a semi-space (in MBytes), the new space consists of twosemi-spaces)type: int default: 0--semi_space_growth_factor (factor by which to grow the new space)type: int default: 2
相关文档里该值是一个以MB
为单位的整数,并没有其他特别的约束。
然而,当用户设置 max_semi_space_size
为200时,Node.js 性能平台 GC Trace分析
结果显示 inactive new_space semispace:256MB
,说明新生代中未使用的那部分是256MB(有关GC的一些知识可以参阅文档最后的列表),如下图所示。
我们也线下验证了一下:
- 当设置
max_smi_space_size
为100,110时,inactive new_space semispace:128MB
。 - 当设置
max_smi_space_size
为50,60时,inactive new_space semispace:64MB
。
那么问题来了,是 Node.js 性能平台的bug?还是v8引擎本身的设计就是如此?
问题定位
其实,从最终64/128/256,这些数值就能推测到,设计就是如此。在计算机的世界里,2的整数次幂会带来很多方便。
还是老方法,既然文档里没有明确说明,而 Node.js 性能平台运行时在该部分功能跟社区运行时是完全一致的,那么只能去代码里找原因了。
一番操作之后,在 deps/v8/src/heap/heap.cc
中找到函数:
bool Heap::ConfigureHeap(size_t max_semi_space_size, size_t max_old_space_size, size_t code_range_size))。
这里摘抄一点max_semi_space
相关代码,相关注释直接写到代码里面了,感兴趣的同学建议去看看完整代码。
bool Heap::ConfigureHeap(size_t max_semi_space_size, size_t max_old_space_size,size_t code_range_size) {if (HasBeenSetUp()) return false;// Overwrite default configuration.// 未设置 max_semi_space_size 时,默认值是 0 if (max_semi_space_size != 0) {max_semi_space_size_ = max_semi_space_size * MB;}...// If max space size flags are specified overwrite the configuration.// 命令行 --max_semi_space_size 设置的新生代大小是通过 FLAG_max_semi_space_size 传递到vif (FLAG_max_semi_space_size > 0) {max_semi_space_size_ = static_cast<size_t>(FLAG_max_semi_space_size) * MB;}.../* ROUND_UP 的定义:// Round up n to be a multiple of sz, where sz is a power of 2.#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))*/// 操作系统相关的内存页大小,我的ubuntu16.04上该值是 512KBif (Page::kPageSize > MB) {max_semi_space_size_ = ROUND_UP(max_semi_space_size_, Page::kPageSize);...}// 该参数默认是falseif (FLAG_stress_compaction) {// This will cause more frequent GCs when stressing.max_semi_space_size_ = MB;}// The new space size must be a power of two to support single-bit testing// for containment.// 关键点在这里// 为什么 50 变成了 64, 100/120 变成了128, 200 变成了 256// 下面的函数 RoundUpToPowerOfTwo32 就是这个变化的原因。/*
uint32_t RoundUpToPowerOfTwo32(uint32_t value) {DCHECK_LE(value, uint32_t{1} << 31);if (value) --value;
// Use computation based on leading zeros if we have compiler support for that.
#if V8_HAS_BUILTIN_CLZ || V8_CC_MSVCreturn 1u << (32 - CountLeadingZeros32(value));
#elsevalue |= value >> 1;value |= value >> 2;value |= value >> 4;value |= value >> 8;value |= value >> 16;return value + 1;
#endif
}*/ max_semi_space_size_ = base::bits::RoundUpToPowerOfTwo32(static_cast<uint32_t>(max_semi_space_size_));// 这里是 min_semi_space_size 的设置,这里不讨论if (FLAG_min_semi_space_size > 0) {...}// 新生代初始大小是 min_semispace_size,如果需要,那么增大到 max_semi_space_sizeinitial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_);if (FLAG_semi_space_growth_factor < 2) {FLAG_semi_space_growth_factor = 2;}...configured_ = true;return true;
}
问题结论
max_semi_space_size
设置看起来是个任意整数,但是实际使用中 v8 会把该值转换成一个不小于该值的2的整数次幂的值。也就是说:
max_semi_space_size
设置为 33, 34, ..., 64,最终结果都是 64MB。max_semi_space_size
设置为 65, 66, ..., 128,最终结果都是 128MB。- 依次类推
heap.cc 里面的注释是
// The new space size must be a power of two to support single-bit testing// for containment.
相关知识
- 解读 V8 GC Log(一): Node.js 应用背景与 GC 基础知识
- 解读 V8 GC Log(二): 堆内外内存的划分与 GC 算法
相关文章:

【FFmpeg】函数详解(二)
FFmpeg函数详解 9、av_dump_format10、avio_open11、avformat_write_header12、avcodec_send_frame13、avcodec_receive_packet9、av_dump_format 原型: void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output);说明: 打印输入输出格式的详…

【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍
游戏开发笔记二十七 Direct3D 11入门级知识介绍作者:毛星云 邮箱: happylifemxy163.com 期待着与志同道合的朋友们相互交流上一节里我们介绍了在迈入DirectX 11的学习旅程之后第一个demo创建的全过程。但由于知识衔接的需要,我们的第一…

英特尔蚕食AMD和NVIDIA?
作者 | Daniel Newman译者 | 苏本如,责编 | 郭芮转载自CSDN(ID:CSDNnews)【编者按】一个鲜为人知的事实是,英特尔凭借其在集成显卡上的领先地位,持续占据着电脑显卡市场的头把交椅。但是随着过去两年中首席…

使用phpStudy运行伊人集项目
1.首次运行时,需要把system/config/install.look.php以及system/config/database.php(后面这个文件可以先不删除,若是安装过程中数据库报错,再来删除它)删除2.若只有一个项目版本需要运行的话,可以把项目拷…

【FFmpeg】函数详解(三)
FFmpeg函数详解 14、av_write_frame15、av_interleaved_write_frame16、av_write_trailer17、avio_close18、av_image_get_buffer_size19、av_image_fill_arrays20、av_rescale_q21、视频格式尺寸转换22、音频重采样:23、将像素格式由索引值转换成字符串24、MD5相关25、avio_h…

php时区问题导致php页面显示不正常
cacti安装成功,但报时区错误,已经做了如下操作,后来发现如上设置还是有此问题 将 /usr/local/php5/php.ini文件内修改如下 date.timezone asia/Chongqing 遂解决之。 转载于:https://blog.51cto.com/itnihao/916148

【FFmpeg】降低转码延迟方法、打印信息详解、refcounted_frames详解
文章目录 1、FFmpeg降低转码延迟方法2、ffmpeg打印信息:源码里打印的这段是这样定义的3、解码时 refcounted_frames 标志的使用3.1 启动该标志3.2 解码后,记得释放3.3 详解1、FFmpeg降低转码延迟方法 关闭sync-lookahead降低rc-lookahead,但别小于10,默认是-1降低threads(比…

速度提升270倍!微软和浙大联合推出全新语音合成系统FastSpeech
作者 | 谭旭转载自微软研究院AI头条(ID: MSRAsia)【编者按】目前,基于神经网络的端到端文本到语音合成技术发展迅速,但仍面临不少问题——合成速度慢、稳定性差、可控性缺乏等。为此,微软亚洲研究院机器学习组和微软&a…

Linux —— 目录(文件夹)及文件相关处理指令
可参考这篇文章:https://mp.weixin.qq.com/s?__bizMzU4MTU3OTI0Mg&mid2247484269&idx1&sn38869a1df48d8cdb6278518b51601ce0&chksmfd443be8ca33b2fe937531e061c406786f0e587d8ab10ff15594442265658d08cd8271ae52c5&mpshare1&scene23&s…

工业级3G路由器
宏电工业级3G路由器的特点,工业级标准设计,适应零上60度的高温,零下30度的低温,存工业级制造工艺,适应交通,环保,矿山,电力等工业级应用,欢迎来电索取解决方案,沈阳宏电办事处 刘冰 15940556464 024-31296279 限东三省地区.转载于:https://blog.51cto.com/lbing/916441

【FFmpeg】AVOutputFormat/AVInputFormat 成员变量 flags 总结
1、分类 AVOutputFormat中flags允许的值: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVEAVInputFormat中flags允许的值…

基础必备 | Python处理文件系统的10种方法
作者 | Jeff Hale 译者 | 风车云马;责编 | Jane,Rachel出品 | Python大本营(ID:pythonnews)【导读】在编写一些Python程序的时候,我们常常需要与文件系统进行交互。在本文中,营长为大家整理了10…

安装Oracle11g先决条件检查失败
体系结构 - 此先决条件将测试系统是否具有认证的体系结构。预期值:?N/A实际值:?N/A?错误列表:?-?PRVF-7536 : 无法在节点 "mywin7" 上执行体系结构检查 ?- Cause:? 无法确定系统体系结构。 ?-Action:? 确保正在使用正确的软件包。 处理 转载于:https://www.…

Windows Forms高级界面组件-使用状态栏控件
状态栏(StatusStrip)控件通常显示在窗体的底部,向用户提供有关应用程序状态的信息。如Word应用程序使用状态栏提供页码、行数和列数的信息。StatusStrip派生于ToolStrip,通常由ToolStripStatusLabel对象组成,用于显示指…

【Qt】在QtCreator中编译log4cplus
在QtCreator中编译log4cplus 一、在QtCreator中配置cmake二、编译log4cplus1、下载2、编译、安装一、在QtCreator中配置cmake 参见博客:https://blog.csdn.net/u010168781/article/details/107613606 log4cplus使用cmake来编译,因此需要QtCreator支持cmake 二、编译log4cpl…

IEEE“撑不住”了?声明解除对华为评审限制
整理 | 琥珀出品 | AI科技大本营(ID:rgznai100)6 月 2 日,IEEE 官方发表声明表示:经美国商务部就出口管制条例在 IEEE 出版活动中的适用性做出的说明,华为及其子公司的员工可以参加 IEEE 出版过程的同行评审和编辑工作…

关于软件产业的两个契机
软件产业是一个产业 , 和其它的产业一样 , 有各种角色分工 。 未来的软件是跨行业的 。 未来 , 软件会将各个行业联系在一起 。 云计算是第一代互联网发展到成熟的标志 。 网格计算是第二代互联网的开始 。 软件产业 在 未来 会 分为 平台&a…

java继承中的一些该注意的问题
关于继承,我想大多数人都知道,它是面向对象语言中的三大特性之一,所以在这里,关于继承的概念等我就不做详细介绍了,我主要就讲一下大家对他的认识中一些比较容易犯的错误吧。 错误认识1、继承,是将父类中所…

【C】printf warning: unknown conversion type character ‘l‘ in format [-Wformat=]
1、问题描述 在使用printf、fprintf打印long long类型时报错 printf warning: unknown conversion type character l in format [-Wformat=]2、原因分析 “%lld” 和 “%llu” 是 linux 下 gcc/g++ 用于 long long int 类型 (64 bits) 输入输出的格式符。 而 “%I64d” 和 “…

史上最强最贵Mac Pro诞生,iPadOS和iOS分家!WWDC19全面总结
作者 | 俞佳兴、胡巍巍转载自CSDN(ID:CSDNnews)图片&视频 | 余佳兴摄自美国圣何塞WWDC现场一年一度的WWDC终于来了!43岁的苹果,产品经验位居世界前列。一个迈入中年的公司,该如何持续做出让人惊艳的产品…

Java 抽象类与接口的区别
接口和抽象类有什么区别 你选择使用接口和抽象类的依据是什么? 接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象 抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人&…

XMOVE3.0手持终端——软件介绍(五):在2KB内存的单片机上实现的T9中文输入法
编者注: X-MOVE是作者在业余时间于2010年6月份启动的以运动传感开发,算法和应用的平台,目前已经发展了三个版本,第四版的开发接近尾声。发布在博客园仅为交流技术,不存在商业目的,作者保留一切权利。 一. 综…

推荐系统遇上深度学习,9篇阿里推荐论文汇总!
作者 | 石晓文转载自小小挖掘机(ID: wAIsjwj)业界常用的推荐系统主要分为两个阶段,召回阶段和精排阶段,当然有时候在最后还会接一些打散或者探索的规则,这点咱们就不考虑了。前面九篇文章中,有三篇是召回阶…

ReSharper修改命名风格
默认情况下,ReSharper会建议你全局变量命名使用下划线开头,且第一个字母小写。否则,会给你标记出来,如下: 但我个人不喜欢这种风格,一般使用首字母大写且不带下划线,可以通过配置来调整…

【Qt】Log4Qt(一)下载、编译
Log4Qt(一)下载、编译 1、下载2、编译2.1 单独编译成库2.2 将源码添加到项目中2.2.1 log4qt.pri分析2.2.2 pro示例如下1、下载 github上星最多的是这个:https://github.com/MEONMedical/Log4Qt 下载log4qt最新(截止2021-12-04)的稳定版本v1.5.1(Qt版本需要Qt5.7.0以上)…

android:退出程序
http://kofi1122.blog.51cto.com/2815761/703751 使用的是定义全局变量的方法

ubuntu中使用apt命令安装ipython失败解决方案
在最近使用ubuntu安装ipython时,出现如下报错: 出现这个问题,主要是因为apt还在运行,故解决方案为: 1、找到并且杀掉所有的apt-get 和apt进程 运行下面的命令来生成所有含有 apt 的进程列表,使用ps和grep命…

【Qt】Log4Qt(二)使用
Log4Qt(二)使用 1、使用TTCCLayout 格式化输出1.1 添加头文件1.2 配置根记录器的输出格式1.3 注册记录器,并输出日志2、最简代码3、将日志写入文件4、使用配置文件:log4qt.properties5、使用配置文件:QSettings6、周期性生成日志文件7、滚动生成日志文件(可以指定日志文件…

B站超全分享!2万人收藏的免费计算机科学速成课
整理 | 一一出品 | AI科技大本营(ID:rgznai100)作为一枚程序员,很多人可能都不太能清晰地说出计算机发展脉络,要想成为优秀的程序员,只会编程是不够的。“读史使人明智”,我们还要了解计算机理论知识&#…

图说:Windows 8使用搜索,快速开启应用
在Windows 8中,“开始菜单”变成的“开始屏幕”,想快速找到需要的应用不是件容易的事,毕竟桌面可以安装太多的应用。 怎么快速找到需要的应用的,其实方法也非常简单,只需在“开始屏幕”下使用键盘,键入需要…