我想确定函数执行时内存中的数组大小。确定数组的大小很容易,但是我看不到数组大小与Lambda执行结束时记录的所用最大内存的相关性。
在设置阵列以及Lambda报告的最大内存使用前后检查process.memoryUsage()
之后,没有明显的着色。我找不到很好的资源来指示Lambda实际如何/用什么来确定所使用的内存。任何帮助将不胜感激?
答案 0 :(得分:3)
这个问题让我自己感到好奇,因此我决定进行一些测试,以了解内存分配如何在AWS Lambda容器内工作。
测试1 :创建内存中具有100,000个元素的数组
内存大小:128MB
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
结果:56 MB
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
googlePlayServicesAuthVersion = "15.0.1"
}
}
测试2 :创建内存中具有1,000,000个元素的数组
内存大小:128MB
exports.handler = async (event) => {
const arr = [];
for (let i = 0; i < 100000; i++) {
arr.push(i);
}
console.log(process.memoryUsage());
return 'done';
};
结果:99 MB
2019-04-30T01:00:59.577Z cd473d5b-986c-436e-8b36-b114410c84cf { rss: 35299328,
heapTotal: 11853824,
heapUsed: 7590320,
external: 8224 }
REPORT RequestId: 2a7548f9-5d2f-4060-8f9e-deb228730d8c Duration: 155.74 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 56 MB
测试3 :创建内存中具有10,000,000个元素的数组
内存大小:128MB
exports.handler = async (event) => {
const arr = [];
for (let i = 0; i < 1000000; i++) {
arr.push(i);
}
console.log(process.memoryUsage());
return 'done';
};
结果:128 MB
2019-04-30T01:03:44.582Z 547a9de8-35f7-48e2-a53f-ab669b188f9a { rss: 80093184,
heapTotal: 55263232,
heapUsed: 52951088,
external: 8224 }
REPORT RequestId: 547a9de8-35f7-48e2-a53f-ab669b188f9a Duration: 801.68 ms Billed Duration: 900 ms Memory Size: 128 MB Max Memory Used: 99 MB
我想我们可以很自信地说,lambda容器使用的内存确实基于内存中数组的大小而增加;在我们的第三个测试中,我们最终消耗了最大的内存并超时。我在这里的假设是,控制lambda执行的进程还监视执行获取的内存量。可能是exports.handler = async (event) => {
const arr = [];
for (let i = 0; i < 10000000; i++) {
arr.push(i);
}
console.log(process.memoryUsage());
return 'done';
};
所反映的。
答案 1 :(得分:2)
好的,所以我使用下面的代码并增加了数组值的数量以获得相关性。对数组的每个最大值进行了三个测试。 Lambda设置为1024MB。每个数组元素的长度为10个字符/字节。
_signOut()
这将输出CSV中使用的以下值:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function GetContainerUsage()
{
const { stdout, stderr } = await exec('cat /proc/meminfo');
// console.log(stdout);
let memInfoSplits = stdout.split(/[\n: ]/).filter( val => val.trim());
// console.log(memInfoSplits[19]); // This returns the "Active" value which seems to be used
return Math.round(memInfoSplits[19] / 1024);
}
function GetMemoryUsage()
{
const used = process.memoryUsage();
for (let key in used)
used[key] = Math.round((used[key] / 1024 / 1024));
return used;
}
exports.handler = async (event, context) =>
{
let max = event.ArrTotal;
let arr = [];
for(let i = 0; i < max; i++)
{
arr.push("1234567890"); //10 Bytes
}
let csvLine = [];
let jsMemUsed = GetMemoryUsage();
let containerMemUsed = await GetContainerUsage();
csvLine.push(event.ArrTotal);
csvLine.push(jsMemUsed.rss);
csvLine.push(jsMemUsed.heapTotal);
csvLine.push(jsMemUsed.heapUsed);
csvLine.push(jsMemUsed.external);
csvLine.push(containerMemUsed);
console.log(csvLine.join(','));
return true;
};
因此,假设有1000万个元素,则该数组为10mil * 10bytes = 100MB。我必须在某处丢失一些开销,因为其他地方使用了大约200MB。但是至少存在明显的线性相关,现在我可以使用它。
答案 2 :(得分:0)
FaaS与PaaS的容量规格
使用lambda函数(FaaS)进行计算的整个想法是,最不费心地进行容量规划。现在,鉴于云提供商无法默认很多选择,因此内存设置和超时是AWS用于配置功能的一些设置。显然,如果进行测试,您可能会发现内存设置不仅决定了内存,而且还决定了CPU计算能力。这是由AWS引用的-
Lambda与配置的内存量成比例地线性分配CPU电源。一个功能具有1,792 MB的容量,相当于一个完整的vCPU(每秒1个vCPU秒的积分)
参考https://docs.aws.amazon.com/lambda/latest/dg/resource-model.html
因此,它不仅足以考虑运行时的内存占用量,而且还足以执行和完成功能所需的CPU速度。 AWS不会指出它们在这些容器中使用的容量或CPU /内存/服务器类型/ IOPS,也不会在任何CW指标(例如EC2实例)中显示使用情况。 因此,我们需要根据测试选择内存设置。
每个lambda(nodejs)都有自己的内存占用空间和专用的节点模块依赖项集。因此,每个人都需要进行负载和性能测试以调整内存和超时设置,并且无法预先计划。
一般研究观察 借助任何基于标准nodejs的lambda函数,该函数具有日志记录功能,并且可以进行世界问候,无需VPC即可部署
降低内存设置本质上并不意味着降低成本,因此基于负载和性能测试的微调是确定可以使用的内存设置的最佳方法。
诸如超时之类的属性仅基于函数完成活动所需的时间,对于批处理作业操作(例如10m)与期望快速响应的Web服务(例如10s)而言,这可能会更高。重要的是避免出现高吞吐量API的情况,因此提早超时而不是等待任何长期未决的依赖关系很重要。在使用API的情况下,缓慢的超时可能导致备用容器(函数)加速扩展以适应新的请求,这也可能会影响托管该函数的子网中分配的IP数量(以防函数在vpc中运行)。
ENI和IP的Lambda限制或帐户/区域内的最大Lambda并发性是规划容量时要考虑的重要因素。 参考https://docs.aws.amazon.com/lambda/latest/dg/limits.html