写入临时文件的数据是否有助于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目录有助于记录的内存使用情况。
更新资料
注意:为了回答这个问题,我使用了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] 删除。
我来说两句