通过多线程优化Lambda成本

2020-12-14 22:26:58

亚马逊已经为您的Lambda功能发布了对10 GB内存和6个vCPU的支持。在本文中,我们将探讨这些新的内存配置选项如何降低兼容工作负载的成本和执行时间。

让我们快速回顾一下Lambda定价方案。我们将忽略免费套餐。 Lambda的每GB每秒收费0.0000166667美元。 GB秒是1 GB内存运行1秒的度量单位。 Lambda通常寿命很短,因此可以说某个特定函数的平均执行时间为100毫秒,每分钟执行100次。这是每分钟10秒的执行时间,每天14.400秒,每30天432.000秒。此功能配置为使用128 MB或RAM(GB的1/8),因此每月需要为432.000 / 8 = 54.000 GB-秒付费。每GB每秒$ 0.0000166667,此功能每月将花费$ 0.90。

Lambda唯一可调整的性能配置是该功能可用的内存量。 CPU性能随内存配置而扩展。过去,Lambda函数始终具有2个vCPU内核,而与内存无关。这些内核将在某些内存配置下受到限制。该文档指出,一个函数具有1,769 MB的空间,相当于一个vCPU。

随着最大内存从3008 MB增加到10GB(AWS新闻-AWS Blog),CPU的数量变得更加灵活。我们进行了一些测试,发现Lambda现在具有以下CPU层:

这打开了许多新的价格调整选项。例如,如果工作负载支持多线程,我们可以尝试优化vCPU的数量以减少执行时间。配置为3009 MB的多线程功能执行速度可能是3008 MB功能的1.5倍,成本降低了33.3%!让我们看看是否可以在现实生活的基准测试中得出这些结果。

为了测试Lambda的性能,我们从源代码中编译了ffmpeg并将其与100 MB示例视频和一个简单的Python应用程序打包在一起。由于此软件包超出了Lambda部署软件包的最大大小,因此我们使用了新的Lambda容器映像支持(AWS News-AWS Blog)将ffmpeg和视频放到一个容器中,并从该容器创建Lambda函数。我们的性能基准将包括视频格式转换的100次迭代。最初运行基准测试的确切命令是ffmpeg -i source.mkv -c:v libx264 -b:a 128k -threads 1 -y /tmp/target.mp4

如您所见,此命令被硬编码为仅使用一个线程。这使我们可以在各种内存配置上设置单线程基准。下表对关键内存大小进行了100次迭代。选择的值是每个CPU层的最高和最低值。要在15分钟内成功转换视频,最少需要832 MB。

此数据清楚地表明,任何高于3008 MB的内存配置都不会提高单线程性能。内存配置最多可节流1769 MB,从1769 MB增加到3008 MB,性能会有一些小幅提高,从3008 MB起,您将使用单个内核的全部容量,这意味着平均执行时间稳定。同时,更高内存配置的成本飞涨。显然,如果您在Lambda中运行单线程进程,则最好使Lambda的内存紧靠函数的实际需求。

对于我们的多线程测试,我们从/ proc / cpuinfo获取CPU数量,并将ffmpeg配置为使用与内核一样多的线程。让我们看一下结果。

立即跳出来的是,使用两个线程的832 MB内存实际上比单线程基准测试慢。这可能与应用于1769 MB以下的Lambda函数的CPU节流有关:争夺相同有限资源的两个线程比拥有这些资源本身的单个线程慢。

在1769 MB时,多线程测量几乎完全等于单线程结果。这是有道理的,因为文档指出该功能为1769 MB,相当于一个vCPU。在这个级别上,竞争显然不再是问题。

在3008 MB(旧的最大内存配置)下,我们开始受益于使用多核。但恰好高出1 MB,即3009 MB,它开始变得很有趣。这是我们第一次使用两个以上的内核,并且我们期望性能会立即提高。但是,在三个内核和3009 MB的结果仅比在两个内核和3008 MB的结果好1.73%。显然,3009 MB的三个内核无法提供3008 MB的两个内核的1.5倍性能,并且正在出现一些节流。基准5307 MB证实了这一点:即使此配置具有相同数量的内核,其性能也比3009 MB时高28.96%。这意味着AWS正在根据其内存配置动态限制该功能可用的处理能力。

接下来,以5308 MB的带宽,我们有了第一个四核基准测试。在这里,我们看到第四个核心增加了重大改进。尽管我们仅添加了0.0188%的内存,但性能却提高了10.65%。其他的四核测量为7076 MB,可以带来进一步的改进,但不足以抵消额外的成本。

然后,在第一个五核基准测试7077 MB处,我们看到了另一个大跃进。同样,我们只添加了一个MB的内存,但是第五个核心将性能提高了令人难以置信的26.56%。将内存增加到8845 MB可以再提高8.64%,但是就像在四核模块中一样,这不能抵消额外的费用。

在8846 MB处,额外的MB和第6个内核可提高5.52%的性能,而10240 MB的最大配置比8846 MB设置快2.87%。

单线程基准测试表明,单个内核在相对较低的内存配置下会达到最大值。相同的逻辑不适用于多线程解决方案:每一层都提高了多线程性能。添加额外的内核有时可以大大提高性能,有时很难增加价值。

这使我得出结论,AWS对Lambda函数应用了一种动态容量上限。例如,此上限可能设置为832 MB处的0.5,这意味着您最多可以使用半个核心。设置为1.0时为1769 MB,这意味着我们可以使用一个完整的内核。在3008,它似乎设置为1.6667。最大值的完整列表可以在下表中找到:

这说明了单线程函数如何完全利用单个内核,但是多线程应用程序不能在多个内核上执行相同的操作。

请注意,这些值适用于我的特定视频转换基准。该基准可能无法使所有可用内核最大化。其他基准可能能够更有效地使用多个内核并产生不同的结果。

核心要点是,该基准测试在不同的内存配置下运行完全相同的过程,并且对于同一CPU层中的更高内存配置始终如一地产生更好的结果。

第二个发现是,添加额外的内核始终会为多线程进程带来性能优势。一些核心(第三个和第六个)提供的收益要小于其他一些核心(第四个和第五个)。如果将功能配置为低于这些阈值之一,则稍微增加该值可能会带来很大收益。

在更高的内存设置下,多线程Lambda函数可以更快地完成,从而降低了成本。通常,较低的执行时间可以抵消较高的内存成本中的很大一部分。这在1769、3009和7077 MB上尤其明显:第一个配置的100次执行费用为$ 1.1602。第二种配置的运行速度提高了41.05%,价格上涨了0.28%(1.1635美元)。 7077 MB设置比1769 MB变体完成74.11%的速度,价格增加3.57%($ 1.2016)。

确定哪个价格点最适合您的工作负载取决于您的要求:如果纯粹出于成本考虑,则最好使用1769 MB或3009 MB。如果是性能驱动的,请以5308、7077和8846 MB运行一些测试。这些内存配置可能会以稍高的成本获得更好的性能。

您可能希望新的高内存Lambda函数也可以提高单线程性能,但是可惜-这些函数似乎在与其最低的3008 MB兄弟姐妹相同的硬件上运行。但是,较高的Lambda层确实包含三个,四个,五个和六个CPU内核。在多线程进程中,内存配置的单个MB差异可能会对函数的执行时间产生重大影响。这使找到理想的价格变得复杂,而不仅仅是将内存配置与您的功能的内存需求相匹配的情况。但是,花一些时间尝试不同的价值可能会节省大量资金。

此外,如果您能够重写单线程Lambda以使用多个线程,则可能会在性能和成本上取得重大收益。

本文是围绕re:Invent 2020发布的系列文章的一部分。如果您想了解有关re:Invent 2020的更多信息,请查看我的其他文章:

我在Twitter上分享此类帖子和较小的新闻文章,请在此处关注我进行定期更新!如果您有任何疑问或评论,或者想与您取得联系,也可以在LinkedIn上找到我。