AWS Lambda内存使用情况以及python代码中的临时文件

kylehyde215:

写入临时文件的数据是否有助于AWS lambda中的内存使用?在lambda函数中,我正在将文件流式传输到临时文件。在lambda日志中,我看到使用的最大内存大于下载的文件。奇怪的是,如果快速连续调用了lambda多次,则下载较小文件的调用仍会报告下载较大文件的调用所使用的最大内存。我将并发限制设置为2。

当我在本地运行代码时,我的内存使用量大约为20MB。在lambda上,它是180MB,大约是流文件的大小。该代码只是使用python请求库流式传输文件下载,然后将文件传输到shutil.copyfileobj()以写入tempfile.TemporaryFile(),然后将其通过管道传递到postgres“从stdin复制”。

这使得/ tmp存储看起来像是占用了内存,但尚未找到任何提及。lambda文档中唯一提到/ tmp的地方是512mb的限制。

示例代码:

import sys
import json
import os
import io
import re
import traceback
import shutil
import tempfile

import boto3
import psycopg2
import requests


def handler(event, context):
    try:
        import_data(event["report_id"])
    except Exception as e:
        notify_failed(e, event)
        raise

def import_data(report_id):
    token = get_token()
    conn = psycopg2.connect(POSTGRES_DSN, connect_timeout=30)
    cur = conn.cursor()

    metadata = load_metadata(report_id, token)
    table = ensure_table(metadata, cur, REPLACE_TABLE)
    conn.commit()
    print(f"report {report_id}: downloading")
    with download_report(report_id, token) as f:
        print(f"report {report_id}: importing data")
        with conn, cur:
            cur.copy_expert(f"COPY {table} FROM STDIN WITH CSV HEADER", f)
        print(f"report {report_id}: data import complete")
    conn.close()


def download_report(report_id, token):
    url = f"https://some_url"
    params = {"includeHeader": True}
    headers = {"authorization": f"Bearer {token['access_token']}"}

    with requests.get(url, params=params, headers=headers, stream=True) as r:
        r.raise_for_status()
        tmp = tempfile.TemporaryFile()
        print("streaming contents to temporary file")
        shutil.copyfileobj(r.raw, tmp)
        tmp.seek(0)
        return tmp


if __name__ == "__main__":
    if len(sys.argv) > 1:
        handler({"report_id": sys.argv[1]}, None)

更新:将代码更改为不使用临时文件,而只是将下载直接流式传输到postgres copy命令后,内存使用情况已修复。让我认为/ tmp目录有助于记录的内存使用情况。

彼得·柯比(Peter Kirby):

更新资料

注意:为了回答这个问题,我使用了Lambdash,尽管我不得不修改用于node8.10的lambda版本。Lambdash是一个简单的小库,可用于从本地终端在lambda上运行shell命令。

AWS Lambdas上的/ tmp目录作为循环设备安装您可以通过运行以下命令(在遵循lambdash的安装说明之后)进行验证:

./lambdash df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       30G  4.0G   26G  14% /
/dev/loop0      526M  872K  514M   1% /tmp
/dev/loop1      6.5M  6.5M     0 100% /var/task

根据https://unix.stackexchange.com/questions/278647/overhead-of-using-loop- Mounted-images-under-linux

通过循环设备访问的数据必须经过两个文件系统层,每个文件层都进行自己的缓存,因此数据最终会被缓存两次,从而浪费大量内存(臭名昭著的“双缓存”问题)

但是,我的猜测是/tmp实际上已保留在内存中。为了对此进行测试,我运行了以下命令:

./lambdash df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       30G  4.0G   26G  14% /
/dev/loop0      526M  1.9M  513M   1% /tmp
/dev/loop1      6.5M  6.5M     0 100% /var/task

./lambdash dd if=/dev/zero of=/tmp/file.txt count=409600 bs=1024
409600+0 records in
409600+0 records out
419430400 bytes (419 MB) copied, 1.39277 s, 301 MB/s

./lambdash df -h
 Filesystem      Size  Used Avail Use% Mounted on
 /dev/xvda1       30G  4.8G   25G  17% /
 /dev/loop2      526M  401M  114M  78% /tmp
 /dev/loop3      6.5M  6.5M     0 100% /var/task

./lambdash df -h
 Filesystem      Size  Used Avail Use% Mounted on
 /dev/xvda1       30G  4.8G   25G  17% /
 /dev/loop2      526M  401M  114M  78% /tmp
 /dev/loop3      6.5M  6.5M     0 100% /var/task

请记住,每次我运行时,都会执行lambda。以下是Lambda的Cloudwatch日志的输出:

07:06:30 START RequestId:4143f502-14a6-11e9-bce4-eff8b92bf218版本:$ LATEST 07:06:30 END RequestId:4143f502-14a6-11e9-bce4-eff8b92bf218 07:06:30报告RequestId:4143f502-14a6- 11e9-bce4-eff8b92bf218持续时间:3.60 ms计费持续时间:100 ms内存大小:1536 MB使用的最大内存:30 MB

07:06:32 START RequestId:429eca30-14a6-11e9-9b0b-edfabd15c79f版本:$ LATEST 07:06:34 END RequestId:429eca30-14a6-11e9-9b0b-edfabd15c79f 07:06:34报告RequestId:429eca30-14a6- 11e9-9b0b-edfabd15c79f持续时间:1396.29 ms计费持续时间:1400 ms内存大小:1536 MB使用的最大内存:430 MB

07:06:36 START RequestId:44a03f03-14a6-11e9-83cf-f375e336ed87版本:$ LATEST 07:06:36 END RequestId:44a03f03-14a6-11e9-83cf-f375e336ed87 07:06:36 REPORT RequestId:44a03f03-14a6- 11e9-83cf-f375e336ed87持续时间:3.69 ms计费持续时间:100 ms内存大小:1536 MB使用的最大内存:431 MB

07:06:38 START RequestId:4606381a-14a6-11e9-a32d-2956620824ab版本:$ LATEST 07:06:38 END RequestId:4606381a-14a6-11e9-a32d-2956620824ab 07:06:38报告RequestId:4606381a-14a6- 11e9-a32d-2956620824ab持续时间:3.63 ms计费持续时间:100 ms内存大小:1536 MB使用的最大内存:431 MB

发生了什么,这意味着什么?

Lambda被执行4次。在第一次执行时,我显示了已安装的设备。在第二次执行时,我/tmp使用允许的500Mb中的401Mb 填充目录中的文件在随后的执行中,我列出了已安装的设备,并显示了它们的可用空间。

第一次执行时的内存利用率为30Mb。后续执行的内存利用率在400Mb范围内。

这证实了/tmp利用率实际上确实有助于内存利用率。

原始答案

我的猜测是,您正在观察的是python或lambda容器本身,在写操作期间将文件缓冲在内存中。

根据https://docs.python.org/3/library/functions.html#open

buffering是用于设置缓冲策略的可选整数。传递0来关闭缓冲(仅在二进制模式下允许),传递1来选择行缓冲(仅在文本模式下可用),并传递一个大于1的整数以指示固定大小的块缓冲区的字节大小。如果未指定任何缓冲参数,则默认的缓冲策略如下:

二进制文件以固定大小的块缓冲;缓冲区的大小是通过试探法来确定底层设备的“块大小”,然后使用io.DEFAULT_BUFFER_SIZE来选择的。在许多系统上,缓冲区的长度通常为4096或8192字节。“交互式”文本文件(isatty()返回True的文件)使用行缓冲。其他文本文件将上述策略用于二进制文件。

tempfile.TemporaryFile()函数具有关键字参数,buffering参数基本上直接传递到上述open调用中。

所以我的猜测是该tempfile.TemporaryFile()函数使用默认open()函数的缓冲设置。您可以尝试tempfile.TemporaryFile(buffering=0)禁用缓冲或tempfile.TemporaryFile(buffering=512)明确设置将数据写入文件时将使用的最大内存量。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

了解python中的内存使用情况

ZipArchive :: close():无法在AWS EC2 Linux中创建临时文件

如何剖析Python中的内存使用情况?

监视Windows版AWS CloudWatch实例中的内存使用情况

Python和Django-如何在内存和临时文件中使用

使用AWS Glue时是否可以访问一个临时文件夹?

我可以在AWS Lambda Function上存储临时文件吗?

缺少具有EC2 +临时文件夹文件的多实例的Drupal 7 + AWS AWS负载均衡器

如何在放大初始化期间配置AWS配置文件的使用情况?

AWS Cognito用户池的跨帐户使用情况以进行登录

Symfony 4,Doctrine和AWS RDS读取副本使用情况

如何通过aws ali获取AWS上“服务配额”中“使用情况”的值?

AWS EC2在crontab上使用python脚本-如何测量使用情况?

使用AWS Lambda(nodejs)获取twilio使用情况数据

如何在AWS中为成本和使用情况数据启用每小时粒度?

打开文件时的Python和内存使用情况

AWS CLI:API网关使用情况未返回所有键的使用情况

如何使用Linq在仅内存DataTable中创建测试/临时文件

Heroku +临时文件系统+ AWS S3

Windows中的内存使用情况

python中每个函数的内存使用情况

Amazon AWS Athena-删除临时文件

自定义 AWS AMI 交换和临时文件夹

AWS Amplify Cache Utility 使用情况

如何从 AWS 控制台了解 elasticseach 存储使用情况

AWS 成本和使用情况报告和关联账户

AWS Sagemaker + AWS Lambda

AWS 按资源标签获取成本和使用情况

AWS 按资源标签获取成本和使用情况