AWS Lambda,特别是Node.js运行时使用什么度量标准来确定所使用的最大内存?

问题描述 投票:3回答:3

我想确定当我的函数执行时数组在内存中的大小。确定数组的大小很容易,但我没有看到我的数组大小与在Lambda执行结束时记录的最大内存的相关性。

在设置阵列之前和之后检查process.memoryUsage()以及Lambda报告的最大内存使用后没有明显的颜色。我找不到一个好的资源来指示Lambda实际用于确定所用内存的方式/内容。任何帮助,将不胜感激?

node.js amazon-web-services aws-lambda
3个回答
3
投票

这个问题让我很好奇,所以我决定运行一些测试来查看内存分配在AWS Lambda容器中的工作原理。

测试1:在内存中创建包含100,000个元素的数组

内存大小:128MB

exports.handler = async (event) => {
    const arr = [];
    for (let i = 0; i < 100000; i++) {
        arr.push(i);
    }
    console.log(process.memoryUsage());
    return 'done';
};

结果:56 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  

测试2:在内存中创建包含1,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';
};

结果:99 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  

测试3:在内存中创建包含10,000,000个元素的数组

内存大小:128MB

exports.handler = async (event) => {
    const arr = [];
    for (let i = 0; i < 10000000; i++) {
        arr.push(i);
    }
    console.log(process.memoryUsage());
    return 'done';
};

结果:128 MB

REPORT RequestId: f1df4f39-e0fc-4b44-8f90-c3c0e3d9c12d  Duration: 3001.33 ms    Billed Duration: 3000 ms    Memory Size: 128 MB Max Memory Used: 128 MB 
2019-04-30T00:54:32.970Z f1df4f39-e0fc-4b44-8f90-c3c0e3d9c12d Task timed out after 3.00 seconds

我想我们可以非常自信地说lambda容器使用的内存会根据内存中数组的大小而上升;在我们的第三次测试中,我们最终完成了记忆和超时。我的假设是控制lambda执行的进程还监视执行获取的内存量;可能由cat /proc/meminfo作为trognanders建议。


2
投票

好的,所以我使用了以下代码并增加了数组值以获得相关性。对阵列的每个最大值进行了三次测试。 Lambda设置为1024MB。每个数组元素长度为10个字符/字节。

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;
};

这将输出CSV中使用的以下值:

Array Count, JS rss, JS heapTotal, JS heapUsed, external, System Active, Lambda reported usage
1,30,7,5,0,53,54
1,31,7,5,0,53,55
1,30,8,5,0,53,55
1000,30,8,5,0,53,55
1000,30,8,5,0,53,55
1000,30,8,5,0,53,55
10000,30,8,5,0,53,55
10000,31,8,6,0,54,56
10000,33,7,5,0,54,57
100000,32,12,7,0,56,57
100000,34,11,8,0,57,59
100000,36,12,10,0,59,61
1000000,64,42,39,0,88,89
1000000,60,36,34,0,84,89
1000000,60,36,34,0,84,89
10000000,271,248,244,0,294,297
10000000,271,248,244,0,295,297
10000000,271,250,244,0,295,297

如果绘图成为:enter image description here

因此,在1000万个元素中,阵列被假定为10mil * 10bytes = 100MB。由于在其他地方使用了大约200MB,因此我必须在某处丢失一些开销。但至少有一个明确的线性相关性,我现在可以使用它。


0
投票

FaaS与PaaS的容量规范

使用lambda函数(FaaS)进行计算的整个想法是对容量规划最少的麻烦。现在,鉴于云提供商无法默认大量选择,内存设置和超时是AWS用于配置功能的一些设置。显然,如果你测试它,你可能会发现内存设置不只是确定内存而且还有CPU计算容量。这是由AWS引用的 -

Lambda与配置的内存量成比例地线性分配CPU功率。在1,792 MB,一个函数相当于1个完整的vCPU(每秒一个vCPU - 秒)

参考https://docs.aws.amazon.com/lambda/latest/dg/resource-model.html

因此,它不仅足以考虑运行时内存占用,而且还考虑它执行和完成功能的CPU速度。 AWS不会调出他们在这些容器中使用的容量或CPU /内存/服务器类型/ IOPS,也不会在EC2实例等任何CW指标中显示该用法。因此我们需要根据测试选择内存设置。

每个lambda(nodejs)都有自己的内存占用和一组专用的节点模块依赖项。因此,每个人都需要加载和性能测试以调整内存和超时设置,并且无法提前计划。

一般研究观察使用任何基于标准nodejs的lambda函数,它具有日志记录并且只是hello world,在没有VPC的情况下部署

  • 128 MB可能会显示150毫秒的执行时间,128 MB的计费时间为200毫秒
  • 256 MB可能会显示80毫秒的执行时间和256 MB的100毫秒的计费

较低的内存设置并不意味着本质上较低的成本,因此基于负载和性能测试的微调是确定可以使用的内存设置的最佳方法。

像超时这样的属性完全基于函数完成活动所需的时间,这对于批处理作业操作(比如说10米)而言要高得多,而网络服务需要快速响应(比如说10秒)。在高吞吐量API的情况下,尽早定时而不是等待任何长期未决的依赖关系对于避免高计费非常重要。在API的情况下,慢速超时可能导致备用容器(功能)旋转以扩展新请求,这也会影响在托管该功能的子网内分配的IP数量(如果函数在vpc内运行)。

Lambda对ENI和IP的限制或帐户/区域内的最大lambda并发性是规划容量时需要考虑的重要因素。参考https://docs.aws.amazon.com/lambda/latest/dg/limits.html

© www.soinside.com 2019 - 2024. All rights reserved.