Javascript Node.js-Segfault:11,具有相当大的数组
这是第二篇文章,这篇文章真让我抓狂。我有一个函数,它处理数组,试图找到类似的数据。该数组包含1410个元素,我认为它们是很多元素,但没有任何节点或我的计算机不能处理。 我的代码给出了“Segmentation Fault:11”错误,我发现这与内存访问问题有关,所以我甚至想测试我的Mac的RAM,但一切都很好。segfault使调试变得非常困难,这就是我来这里的原因 出现问题的代码在此处:Javascript Node.js-Segfault:11,具有相当大的数组,javascript,arrays,node.js,segmentation-fault,Javascript,Arrays,Node.js,Segmentation Fault,这是第二篇文章,这篇文章真让我抓狂。我有一个函数,它处理数组,试图找到类似的数据。该数组包含1410个元素,我认为它们是很多元素,但没有任何节点或我的计算机不能处理。 我的代码给出了“Segmentation Fault:11”错误,我发现这与内存访问问题有关,所以我甚至想测试我的Mac的RAM,但一切都很好。segfault使调试变得非常困难,这就是我来这里的原因 出现问题的代码在此处: return matchings.map(matchArray => { const names
return matchings.map(matchArray => {
const namesList = matchArray
.map(matchItem => matchItem.name)
.sort((a, b) => a.localeCompare(b))
const symbolsList = matchArray
.map(matchItem => matchItem.symbol)
.sort((a, b) => a.localeCompare(b))
return {
name: common.getMode(namesList),
symbol: common.getMode(symbolsList),
matches: matchArray
}
}).sort((a, b) => a.name.localeCompare(b.name))
其中,matchings
是我所说的数组common.getMode(数组)
具有以下代码:
array.sort()
const stats = {
top: {
name: '',
freq: 0
},
current: {
name: array[0],
freq: 1
}
}
for (let idxName = 1; idxName < array.length; idxName++) {
const currentName = array[idxName]
const lastName = array[idxName - 1]
if (currentName === lastName) {
stats.current.freq++
} else {
if (stats.current.freq > stats.top.freq) {
stats.top.name = stats.current.name
stats.top.freq = stats.current.freq
}
stats.current = {
name: currentName,
freq: 1
}
}
}
if (stats.current.freq > stats.top.freq) {
stats.top.name = stats.current.name
stats.top.freq = stats.current.freq
}
return stats.top.name
array.sort()
常数统计={
顶部:{
名称:“”,
频率:0
},
当前:{
名称:数组[0],
频率:1
}
}
for(让idxName=1;idxNamestats.top.freq){
stats.top.name=stats.current.name
stats.top.freq=stats.current.freq
}
stats.current={
姓名:currentName,
频率:1
}
}
}
如果(stats.current.freq>stats.top.freq){
stats.top.name=stats.current.name
stats.top.freq=stats.current.freq
}
return stats.top.name
值得一提的是,当使用较小的数组(1000)执行时,代码运行良好,这让我相信它不是我的代码。在线上也很少有关于节点SEGFULT 11的内容,这是没有帮助的
非常感谢您的任何想法 TL;DR使用从调用堆栈中消除应力 编辑(附说明) 请参阅以了解
调用堆栈
、内存堆
和队列
之间的区别。尽管对象和变量存在于堆
land中,但函数调用在调用堆栈
中引用,您的第二个数据集耗尽了该堆栈(16'000个堆栈帧);因此,您的算法无法跟上,因为它无法继续分配新的函数调用
请参阅,其中指向有关调用堆栈的更多信息,以及指向获取堆上数据的方法
原始答案
我可能完全不感兴趣,但我很想看看将循环转换为递归是否有助于内存处理。我想在我的盒子上试一试,但把一切都安排好是件麻烦事
你能试试这个吗?它使用扩展运算符和数组分解,因此您可能需要将babel-preset-stage-0添加到项目和.babelrc
文件中
Javascript
let common = {};
common.getMode = (arr, compare_fn) => {
const compare = !!compare_fn ? compare_fn : (a, b) => a.localeCompare(b)
arr.sort(compare)
const stats = {
top: {
name: '',
freq: 0
},
current: {
name: arr[0],
freq: 1
}
}
for (let i=1, imax = arr.length ; i < imax ; ++i) {
const currentName = arr[i]
const lastName = arr[i - 1]
if (currentName === lastName) {
stats.current.freq++
} else {
if (stats.current.freq > stats.top.freq) {
stats.top.name = stats.current.name
stats.top.freq = stats.current.freq
}
stats.current = {
name: currentName,
freq: 1
}
}
}
if (stats.current.freq > stats.top.freq) {
stats.top.name = stats.current.name
stats.top.freq = stats.current.freq
}
return stats.top.name
};
const build_prop_list = (prop, input_array, output_array = []) => {
if(input_array.length == 0) return output_array;
else {
const [current, ...tail] = input_array;
const new_array = [...output_array, current[prop]];
return build_prop_list(prop, tail, new_array);
}
}
const work = (input_array, output_array = []) => {
if(input_array.length == 0) return output_array.sort((a, b) => a.name.localeCompare(b.name));
else {
const [matchArray, ...tail] = input_array;
const namesList = build_prop_list("name", matchArray);
const symbolsList = build_prop_list("symbol", matchArray);
const new_element = {
name: common.getMode(namesList),
symbol: common.getMode(symbolsList),
matches: matchArray
};
const new_array = [...output_array, new_element];
return work(tail, new_array);
}
}
let result = work(insert_your_json_here);
谢谢你的回复。非工作数组的JSON在这里:工作数组在这里:。有没有可能是因为等待承诺超时,因为函数在给出SEGFULT之前大约需要8秒?您似乎已经解决了它,非常感谢。是否存在导致这种情况的节点限制?我在运行代码时监视内存使用情况,内存似乎很好。我认为Node应该能够处理这个问题,不是吗?这叫做尾部调用优化。基本上,从堆栈按其参数的数量成比例增长到应该增长到固定大小的堆栈(取决于在函数内分支或调用其他函数的次数)。我会试着为你参考一些文献。我不认为它依赖于节点。这是一个在任何语言和计算机上都会出现的问题。您还可以在common.getMode(…)
中优化循环,但是第一次迭代的行为会发生变化。我也会将其作为编辑来编写。请参见和。其思想是不要在函数末尾分支到另一个函数或求值,而是使用递归为您执行循环。如果对你有帮助的话,你也可以对答案进行投票。我已经试着对答案进行投票,这太棒了,但是我的声誉目前还不到15。我明天去看看,因为我太累了。再次感谢Sumi!我回来了,苏米。我已经仔细看过了你的编辑,并对整件事做了大量的研究。我真的很高兴您提供的代码能够正常工作,但是我正在尝试找出SEGFULT的真正原因,因为这将帮助我更好地理解JS和V8。我已经能够确认没有由于记录new Error.stack
而导致调用堆栈溢出,并且堆栈上只有两到三个调用。我还使用了process.memoryUsage()
并比较了heapTotal
和heapUsed
,这表明我还有约5MB的堆空间。
const feed = (input_array) => {
if(input_array.length == 0) return;
const [lastName, currentName, ...tail] = input_array;
if (currentName === lastName) {
stats.current.freq++
} else {
if (stats.current.freq > stats.top.freq) {
stats.top.name = stats.current.name
stats.top.freq = stats.current.freq
}
stats.current = {
name: currentName,
freq: 1
}
}
return feed(tail);
}(arr);