如何修复 JavaScript 堆内存不足
How to fix JavaScript heap out of memory
我正在使用 google 操作控制台。这里我有一个 webhook,见下面的代码。现在,当我 运行 出现以下错误时:
致命错误:CALL_AND_RETRY_LAST 分配失败 - JavaScript 堆内存不足
const {
conversation,
Simple,
Canvas,
Card,
Link,
Suggestion,
Image,
} = require('@assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
const categories = {
nhgooi: {
antwoorden: [
'Ze willen dat pedojager onmiddelijk stoppen.',
'Ze willen dat pedojagers zo doorgaan.',
'Ze willen dat pedojagers pedofielen nog harder aanpakken.',
'Ze willen dat pedojagers pedofielen blijven zoeken maar ze minder hard aanpakken.',
],
vraag: [
"Wat wilt de politie dat pedojagers doen?"
],
image: {
url: "https://storage.googleapis.com/gweb-uniblog-publish-prod/images/" +
"Search_GSA.2e16d0ba.fill-300x300.png",
alt: 'Google app logo',
},
},
};
function randomarray(i_array, antwoorden, category){ //make an array with items in random order
while (i_array.length > 0){
i = Math.floor(Math.random() * i_array.length);
var index = i - 1;
antwoorden.push(categories[category].antwoorden[index]);
delete i_array[index];
}
return antwoorden;
}
app.handle('NieuwsQuiz_Vragen', (conv) => {
var antwoorden = [];
var i_array = [0, 1, 2, 3];
const category = conv.scene.slots.vraag_categorie.value; //gekozen categorie (regio)
const vraag = categories[category].vraag[0];
const antwoorden_shuffled = randomarray(i_array, antwoorden, category);
const antwoorden_string = antwoorden_shuffled.toString();
const image = categories[category].image[0];
const prefix = `Jij hebt gekozen voor vragen uit ${category}, laten we snel beginnen!`;
conv.add(prefix);
const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
if (supportsRichResponse) {
conv.add(new Card({
title: vraag,
subtitle: antwoorden_string,
image: new Image(image),
button: new Link({
name: 'Learn more',
open: {
url: 'https://www.google.com/about/'
}
})
}));
}
// conv.add(new Simple({
// speech: `${prefix} ${vraag}`,
// text: vraag,
// }));
// for( let i=0 ; i <= antwoorden.length ; i++ ) {
// conv.add(new Suggestion({title: antwoorden[i]}));
// }
//conv.add(new Suggestion({title: 'Quit'}));
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
有人知道如何解决这个问题吗?我已经在 Stack 上调查了有关此问题的其他问题,但所有这些解决方案都是在终端而不是在 webhook 中使用。
您的代码通常不应发生 OOM 异常,因为默认内存分配为 256MB 或 512MB,这远远超出您的需要。这使我相信您的代码中存在内存泄漏。
仔细一看,在我看来,randomarray
正在做这件事,就像您在 while 循环中进行数组操作一样,如果您不小心,这两者都可能无穷无尽。
我已经在下面复制了你的 randomarray 函数:
// make an array with items in random order
function randomarray(i_array, antwoorden, category){
while (i_array.length > 0){
i = Math.floor(Math.random() * i_array.length);
var index = i - 1;
antwoorden.push(categories[category].antwoorden[index]);
delete i_array[index];
}
return antwoorden;
}
根据您的意见,我相信您想要的是一个数组随机播放功能。
在这里使用:
var antwoorden = [];
var i_array = [0, 1, 2, 3];
const category = conv.scene.slots.vraag_categorie.value; //gekozen categorie (regio)
const vraag = categories[category].vraag[0];
const antwoorden_shuffled = randomarray(i_array, antwoorden, category);
如果我自己重现这个函数并添加几行来观察会发生什么,我会得到:
i_array: [,1,2,3] (Length 4)
i_array: [,,2,3] (Length 4)
i_array: [,,,3] (Length 4)
i_array: [,,,3] (Length 4)
i_array: [,,,3] (Length 4)
...
这似乎无限循环,每次都将您的响应之一添加到数组中。一段时间后,数组会变得太大而崩溃。
为什么会这样?您的实施似乎有一些错误。
您有一个设置为 i - 1
的 index
变量。这是不正确的,因为算法 Math.floor(Math.random() * i_array.length)
每次都会正确 return 一个有效索引。 index
的实现将始终错过数组中的最后一个元素,从而导致循环永远继续下去。
delete
命令将删除特定索引中的值,但不会更改数组长度。相反,您的数组的值为 [empty, empty, empty, empty]
,一个长度仍为 4 的数组。当您计算直到长度为 0 时,此循环将永远不会结束。使用splice
方法将从数组中移除元素并且减少数组长度。
function randomarray(i_array, antwoorden, category){
while (i_array.length > 0) {
i = Math.floor(Math.random() * i_array.length);
antwoorden.push(categories[category].antwoorden[i]);
i_array.splice(i, 1)
}
return antwoorden;
}
您可以进行这些修复,或者考虑使用现成的 npm module to shuffle arrays。
致命错误:CALL_AND_RETRY_LAST 分配失败 - JavaScript 堆内存不足
const {
conversation,
Simple,
Canvas,
Card,
Link,
Suggestion,
Image,
} = require('@assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
const categories = {
nhgooi: {
antwoorden: [
'Ze willen dat pedojager onmiddelijk stoppen.',
'Ze willen dat pedojagers zo doorgaan.',
'Ze willen dat pedojagers pedofielen nog harder aanpakken.',
'Ze willen dat pedojagers pedofielen blijven zoeken maar ze minder hard aanpakken.',
],
vraag: [
"Wat wilt de politie dat pedojagers doen?"
],
image: {
url: "https://storage.googleapis.com/gweb-uniblog-publish-prod/images/" +
"Search_GSA.2e16d0ba.fill-300x300.png",
alt: 'Google app logo',
},
},
};
function randomarray(i_array, antwoorden, category){ //make an array with items in random order
while (i_array.length > 0){
i = Math.floor(Math.random() * i_array.length);
var index = i - 1;
antwoorden.push(categories[category].antwoorden[index]);
delete i_array[index];
}
return antwoorden;
}
app.handle('NieuwsQuiz_Vragen', (conv) => {
var antwoorden = [];
var i_array = [0, 1, 2, 3];
const category = conv.scene.slots.vraag_categorie.value; //gekozen categorie (regio)
const vraag = categories[category].vraag[0];
const antwoorden_shuffled = randomarray(i_array, antwoorden, category);
const antwoorden_string = antwoorden_shuffled.toString();
const image = categories[category].image[0];
const prefix = `Jij hebt gekozen voor vragen uit ${category}, laten we snel beginnen!`;
conv.add(prefix);
const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
if (supportsRichResponse) {
conv.add(new Card({
title: vraag,
subtitle: antwoorden_string,
image: new Image(image),
button: new Link({
name: 'Learn more',
open: {
url: 'https://www.google.com/about/'
}
})
}));
}
// conv.add(new Simple({
// speech: `${prefix} ${vraag}`,
// text: vraag,
// }));
// for( let i=0 ; i <= antwoorden.length ; i++ ) {
// conv.add(new Suggestion({title: antwoorden[i]}));
// }
//conv.add(new Suggestion({title: 'Quit'}));
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
有人知道如何解决这个问题吗?我已经在 Stack 上调查了有关此问题的其他问题,但所有这些解决方案都是在终端而不是在 webhook 中使用。
您的代码通常不应发生 OOM 异常,因为默认内存分配为 256MB 或 512MB,这远远超出您的需要。这使我相信您的代码中存在内存泄漏。
仔细一看,在我看来,randomarray
正在做这件事,就像您在 while 循环中进行数组操作一样,如果您不小心,这两者都可能无穷无尽。
我已经在下面复制了你的 randomarray 函数:
// make an array with items in random order
function randomarray(i_array, antwoorden, category){
while (i_array.length > 0){
i = Math.floor(Math.random() * i_array.length);
var index = i - 1;
antwoorden.push(categories[category].antwoorden[index]);
delete i_array[index];
}
return antwoorden;
}
根据您的意见,我相信您想要的是一个数组随机播放功能。 在这里使用:
var antwoorden = [];
var i_array = [0, 1, 2, 3];
const category = conv.scene.slots.vraag_categorie.value; //gekozen categorie (regio)
const vraag = categories[category].vraag[0];
const antwoorden_shuffled = randomarray(i_array, antwoorden, category);
如果我自己重现这个函数并添加几行来观察会发生什么,我会得到:
i_array: [,1,2,3] (Length 4)
i_array: [,,2,3] (Length 4)
i_array: [,,,3] (Length 4)
i_array: [,,,3] (Length 4)
i_array: [,,,3] (Length 4)
...
这似乎无限循环,每次都将您的响应之一添加到数组中。一段时间后,数组会变得太大而崩溃。
为什么会这样?您的实施似乎有一些错误。
您有一个设置为
i - 1
的index
变量。这是不正确的,因为算法Math.floor(Math.random() * i_array.length)
每次都会正确 return 一个有效索引。index
的实现将始终错过数组中的最后一个元素,从而导致循环永远继续下去。delete
命令将删除特定索引中的值,但不会更改数组长度。相反,您的数组的值为[empty, empty, empty, empty]
,一个长度仍为 4 的数组。当您计算直到长度为 0 时,此循环将永远不会结束。使用splice
方法将从数组中移除元素并且减少数组长度。
function randomarray(i_array, antwoorden, category){
while (i_array.length > 0) {
i = Math.floor(Math.random() * i_array.length);
antwoorden.push(categories[category].antwoorden[i]);
i_array.splice(i, 1)
}
return antwoorden;
}
您可以进行这些修复,或者考虑使用现成的 npm module to shuffle arrays。