使用多个线程

时间:2015-11-05 14:21:53

标签: python multithreading amazon-web-services amazon-dynamodb aws-lambda

免责声明:我知道这个问题会让一些人感到烦恼,因为它含糊不清,理论上很少,代码很少。

我在Python中有一个AWS Lambda函数,它从S3读取非规范化记录文件,正确格式化其内容,然后通过批量写入将其上传到DynamoDB。这一切都像广告宣传的那样。然后我尝试将此管道的上传部分分解为线程,希望能更有效地利用DynamoDBs的写入容量。但是,多线程版本的速度降低了大约50%。由于代码很长,我已经包含伪代码。

NUM_THREADS = 4
for every line in the file:
   Add line to list of lines
   if we've read enough lines for a single thread:
       Create thread that uploads list of lines
       thread.start()
       clear list of lines.

for every thread started:
    thread.join()

到目前为止我已检查过的重要说明和可能的问题来源:

  • 使用DynamoDB Local在本地测试时,线程确实使我的程序运行得更快。
  • 如果我只使用1个线程,或者即使我使用多个线程但我在启动它之后立即加入线程(实际上是单线程),程序完成得更快。 1螺纹~30s,多螺纹~45s。
  • 线程之间没有共享内存,没有锁等等。
  • 我尝试为每个线程创建新的DynamoDB连接并改为共享一个连接,但没有任何效果。
  • 我已经确认添加更多线程并不会超过DynamoDB的写入容量,因为它会产生相同数量的批量写入请求,并且我在整个执行过程中没有比使用单个线程更多的未处理项目。
  • 线程改善执行时间,因为程序是网络绑定的,即使Python线程实际上并不在多个核心上运行。
  • 我尝试先读取整个文件,然后生成所有线程,认为最好不要中断磁盘IO,但是没有效果。
  • 我已尝试过Thread库以及Process库。

我再次知道这个问题非常理论化,所以可能很难看出问题的根源,但是有一些我不知道的Lambda怪癖吗?有什么我可以尝试帮助诊断问题吗?任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

Nate,您是否完全排除了Dynamodb端的问题?写请求的总数可能相同,但是多线程的数字每秒会有所不同。

控制台有一些有用的图表,可以显示您的写入(或批量写入)是否受到限制。如果你在Lambda函数中没有正确的“后退,重试”逻辑,Lambda将尝试再试一次,你的问题会变得更糟。

另一件事,对你来说可能是显而易见的(但不是我!)。我的印象是batch_writes在容量规划方面为您节省了资金。 (例如,200个批量写入的20个只会花费你10个写入单位。我可以发誓我听到一个AWS人员在演示中提到这一点,但这不是重点。)

事实上,batch_writes可以节省你一些时间,但没有经济效益。

最后一个想法:我敢打赌,Lambda处理时间比提高Dynamodb写入容量便宜。如果你没有特别急于让Lambda完成,为什么不让它在单线程上运行呢?

祝你好运!

答案 1 :(得分:0)

事实证明,线程更快,但仅在文件达到特定文件大小时。我最初的工作文件大小约为1/2 MG。使用10 MG文件,线程版本的速度提高了大约50%。仍然不确定为什么它不适用于较小的文件,也许只需要时间来获取'烹饪,你知道我的意思吗?电脑是喜怒无常的东西。

答案 2 :(得分:0)

作为背景,我对python和dynamoDB以及使用python的多处理库有很好的经验。由于您的文件大小相当小,因此可能是该过程的设置时间使您对性能感到困惑。如果您还没有,请使用python多处理池,并根据您的用例使用map或imap,如果您需要将任何数据传回主线程。使用池是在python中运行多个进程的最简单方法。如果您需要将应用程序作为优先级更快地运行,您可能需要考虑使用golang并发,并且您始终可以将代码构建为二进制文件以在python中使用。欢呼声。