JavaScript数组在13k-16k元素时性能下降原因问询
数组创建与编辑性能测试异常分析
测试背景
我针对数组的创建与编辑性能开展测试,发现元素量约在13k-16k的数组存在异常特性。
测试说明
以下图表展示了数组创建及读取(求和操作)时的单元素耗时。capacity和push代表两种数组创建方式:
- capacity:
const arr = new Array(length)后执行arr[i] = data - push:
const arr = [];后执行arr.push(data)
测试图表
- 数组创建耗时随长度变化图
- 数组操作耗时随长度变化图
测试结果
数组创建与读取操作的单元素耗时,相比元素量少1k的情况均下降约2-3倍。使用push方式创建数组时,性能骤降出现得比预分配容量的方式更早,推测是因为push时数组容量耗尽会额外分配更多空间,更早触发了性能较慢的执行路径。
测试代码可查看对应github仓库
核心问题
为何数组在13k-16k元素左右时性能会下降?
我推测V8引擎从该元素量开始对大数组采用不同处理逻辑以优化性能,但临界点过早,导致优化生效前先出现性能下降。能看到约500元素后性能逐步下降,骤降后又回升,遗憾的是我未找到相关资料。
另外,若有人知道预分配容量创建数组末尾、push创建数组求和时出现峰值的原因,也欢迎告知 :)
补充测试1
按照建议,在另一台配置更低的机器上重复测试以排除缓存影响,结果高度相似:
- 另一台机器数组创建耗时图
- 另一台机器数组操作耗时图
补充测试2
我使用--allow-natives-syntax启动Node.js,通过%DebugPrint(array);打印数组调试日志,期望发现不同长度数组的差异,但除长度和内存地址外均一致,示例如下:
// For array created with capacity DebugPrint: 000002CB8E1ACE19: [JSArray] - map: 0x035206283321 <Map(HOLEY_SMI_ELEMENTS)> [FastProperties] - prototype: 0x036b86245b19 <JSArray[0]> - elements: 0x02cb8e1ace39 <FixedArray[1]> [HOLEY_SMI_ELEMENTS] - length: 1 - properties: 0x0114c5d01309 <FixedArray[0]> - All own properties (excluding elements): { 00000114C5D04D41: [String] in ReadOnlySpace: #length: 0x03f907ac1189 <AccessorInfo> (const accessor descriptor), location: descriptor } 0000035206283321: [Map] - type: JS_ARRAY_TYPE - instance size: 32 - inobject properties: 0 - elements kind: HOLEY_SMI_ELEMENTS - unused property fields: 0 - enum length: invalid - back pointer: 0x035206283369 <Map(PACKED_SMI_ELEMENTS)> - prototype_validity cell: 0x03f907ac15e9 <Cell value= 1> - instance descriptors #1: 0x009994a6aa31 <DescriptorArray[1]> - transitions #1: 0x009994a6a9d1 <TransitionArray[4]>Transition array #1: 0x0114c5d05949 <Symbol: (elements_transition_symbol)>: (transition to PACKED_DOUBLE_ELEMENTS) -> 0x0352062832d9 <Map(PACKED_DOUBLE_ELEMENTS)> - prototype: 0x036b86245b19 <JSArray[0]> - constructor: 0x031474c124e9 <JSFunction Array (sfi = 000003CECD93C3A9)> - dependent code: 0x0114c5d01239 <Other heap object (WEAK_FIXED_ARRAY_TYPE)> - construction counter: 0 // For array created with push DebugPrint: 000003B09882CE19: [JSArray] - map: 0x02ff94f83369 <Map(PACKED_SMI_ELEMENTS)> [FastProperties] - prototype: 0x0329b3805b19 <JSArray[0]> - elements: 0x03b09882ce39 <FixedArray[17]> [PACKED_SMI_ELEMENTS] - length: 1 - properties: 0x03167aa81309 <FixedArray[0]> - All own properties (excluding elements): { 000003167AA84D41: [String] in ReadOnlySpace: #length: 0x02094f941189 <AccessorInfo> (const accessor descriptor), location: descriptor } 000002FF94F83369: [Map] - type: JS_ARRAY_TYPE - instance size: 32 - inobject properties: 0 - elements kind: PACKED_SMI_ELEMENTS - unused property fields: 0 - enum length: invalid - back pointer: 0x03167aa81599 <undefined> - prototype_validity cell: 0x02094f9415e9 <Cell value= 1> - instance descriptors #1: 0x00d25122aa31 <DescriptorArray[1]> - transitions #1: 0x00d25122aa01 <TransitionArray[4]>Transition array #1: 0x03167aa85949 <Symbol: (elements_transition_symbol)>: (transition to HOLEY_SMI_ELEMENTS) -> 0x02ff94f83321 <Map(HOLEY_SMI_ELEMENTS)> - prototype: 0x0329b3805b19 <JSArray[0]> - constructor: 0x009ff8a524e9 <JSFunction Array (sfi = 0000025A84ABC3A9)> - dependent code: 0x03167aa81239 <Other heap object (WEAK_FIXED_ARRAY_TYPE)> - construction counter: 0
补充测试3
求和操作的性能下降出现在数组大小从13_994变为13_995时:
- 求和性能骤降临界点图
内容的提问来源于stack exchange,提问作者Teiem
相关产品推荐
相关产品推荐

