为什么 Exiftool 很慢,从 stdin 读取内存占用很大;快速,小的磁盘读取
Why is Exiftool slow, memory hog reading from stdin; fast, small reading from disk
我正在调用 exiftool 从 5GB 及以上的大视频中提取 XMP 标签,如描述。我的应用程序是 Python,我看到一些文件会耗尽内存;我这样调用它:
fp = open('9502_UAS_2.mov', 'rb')
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -'
exiftool = subprocess.Popen(CMD.split(),
stdin=fp,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(json_bytes, stderr) = exiftool.communicate()
为了找出问题所在,我尝试了 CLI 上的变体。这表明从磁盘上的文件读取速度很快并且使用很少的 RAM,而从 STDIN 读取(重新创建上面读取的文件指针)非常慢并且使用大量 RAM(我已经删除了输出 JSON 下面的元数据为清楚起见):
time exiftool -api largefilesupport=1 -sort -a -S -G -struct -j 9502_UAS.mov
real 0m0.196s
time cat 9502_UAS.mov | exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -
real 0m33.514s
'top' 显示第二个在这个 5.1GB 的视频文件上消耗了高达 1.4GB 的内存。
我想了解为什么从 STDIN 读取速度很慢并且消耗大量内存,因此我可以注意服务器上的内存耗尽等限制。 exiftool 是否按顺序读取缓冲文件的整个 STDIN 流,直到它获得解析元数据所需的二进制信息?不是seek()-来回查找需要的吗?
相反,为什么 运行 它对本机磁盘文件这么快? exiftool 是否使用内存映射文件系统快速跳转到它需要解析的文件部分?
理想情况下,我会从 STDIN 读取,因为实际应用程序的文件源是 AWS S3 存储桶,如果可以避免,我不想将文件复制到本地 AWS EC2 磁盘,所以任何提示有效阅读标准输入会有所帮助。
谢谢。
好吧,您将整个内容传递给示例中的 stdin
。当然,这需要时间。最好将文件名传递给外部工具:
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j {}'
exiftool = subprocess.Popen(CMD.format('9502_UAS_2.mov').split(),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
json_bytes, stderr = exiftool.communicate()
当传递给 stdin
时,首先整个文件将通过管道传输到程序,只有在完成此过程后,该过程才会停止(无论工具是否已经完成其工作)。
当文件位于远程服务器上时,您需要在该服务器上 运行 此脚本,将文件复制到本地文件,或者读取文件的前 n
个字节文件并仅将这些传递给 exiftool。 (确定要留多大 n
作为练习...)
我正在调用 exiftool 从 5GB 及以上的大视频中提取 XMP 标签,如描述。我的应用程序是 Python,我看到一些文件会耗尽内存;我这样调用它:
fp = open('9502_UAS_2.mov', 'rb')
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -'
exiftool = subprocess.Popen(CMD.split(),
stdin=fp,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(json_bytes, stderr) = exiftool.communicate()
为了找出问题所在,我尝试了 CLI 上的变体。这表明从磁盘上的文件读取速度很快并且使用很少的 RAM,而从 STDIN 读取(重新创建上面读取的文件指针)非常慢并且使用大量 RAM(我已经删除了输出 JSON 下面的元数据为清楚起见):
time exiftool -api largefilesupport=1 -sort -a -S -G -struct -j 9502_UAS.mov
real 0m0.196s
time cat 9502_UAS.mov | exiftool -api largefilesupport=1 -sort -a -S -G -struct -j -
real 0m33.514s
'top' 显示第二个在这个 5.1GB 的视频文件上消耗了高达 1.4GB 的内存。
我想了解为什么从 STDIN 读取速度很慢并且消耗大量内存,因此我可以注意服务器上的内存耗尽等限制。 exiftool 是否按顺序读取缓冲文件的整个 STDIN 流,直到它获得解析元数据所需的二进制信息?不是seek()-来回查找需要的吗?
相反,为什么 运行 它对本机磁盘文件这么快? exiftool 是否使用内存映射文件系统快速跳转到它需要解析的文件部分?
理想情况下,我会从 STDIN 读取,因为实际应用程序的文件源是 AWS S3 存储桶,如果可以避免,我不想将文件复制到本地 AWS EC2 磁盘,所以任何提示有效阅读标准输入会有所帮助。
谢谢。
好吧,您将整个内容传递给示例中的 stdin
。当然,这需要时间。最好将文件名传递给外部工具:
CMD = 'exiftool -api largefilesupport=1 -sort -a -S -G -struct -j {}'
exiftool = subprocess.Popen(CMD.format('9502_UAS_2.mov').split(),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
json_bytes, stderr = exiftool.communicate()
当传递给 stdin
时,首先整个文件将通过管道传输到程序,只有在完成此过程后,该过程才会停止(无论工具是否已经完成其工作)。
当文件位于远程服务器上时,您需要在该服务器上 运行 此脚本,将文件复制到本地文件,或者读取文件的前 n
个字节文件并仅将这些传递给 exiftool。 (确定要留多大 n
作为练习...)