需要统计服务器上的视频信息,写了个脚本,使用 MediaInfo 获取视频信息,但是因为文件数量比较多,便利效率比较低(单进程每秒 1.5 个文件),后来使用了 Multiprocessing 多进程,可以达到效率是高了,但是一个小时也才能获取到 1.5 万左右的文件信息。
求问,有什么比较好的方法可以较高提高效率么?
注:视频文件在文件服务器上,千兆网络挂载过来,使用了 Multiprocessing 后,遍历时速度带宽大约到了 800~900M,主要代码如下:
pool_size = multiprocessing.cpu_count() * 2 - 4
with multiprocessing.Pool(pool_size) as Pool:
walk = os.walk(path)
fn_gen = itertools.chain.from_iterable((os.path.join(root, file) for file in files) for root, dirs, files in walk)
Pool.map(video_handler, fn_gen)
1
mrytsr 2016-12-18 09:12:22 +08:00 via Android
ffprobe
|
2
Septembers 2016-12-18 10:44:59 +08:00 2
用 pymediainfo 然后在本地执行
(只是获取 mediainfo 并不需要完整读取文件 (但是你通过网络挂载的话可能不支持 seek 导致需要读取完整文件 (这或许是主要导致慢的原因 |
3
264768502 2016-12-18 12:09:15 +08:00 via Android 1
这个 io 是瓶颈,试试多线程的线程池(可以试试开到 10 以上)+pymediainfo(mediainfo 的源代码里有 python 的用例)
网络挂载是 smb/nfs/webdav/ftp? |
4
tinypig OP |
5
264768502 2016-12-18 16:23:01 +08:00 via Android 1
如果有机会的话可以换个协议么,比如 nfs
说 cpu 负载是说本地还是服务器的呢 cifs/smb 也有可能是服务器单核性能的瓶颈 另外最好是用协程的 pool,会比线程进程池更高效.(除非视频处理跟复杂,那样的话还是用进程池) |
6
tinypig OP @264768502
CPU 负载是说本地负载。 我昨天试过用 Gevent.Pool ,效率不高,跟单进程的差不多,也有可能是我用的方式不对,我只是把上面 Multiprocessing 的 pool 换成了 gevent 的 pool 。 |
7
Septembers 2016-12-18 18:04:17 +08:00 via iPad
@tinypig 建议放置在 远程执行
|
8
goodniuniu 2016-12-18 18:23:29 +08:00 via iPhone
明天回去试试代码,感觉瓶颈在网络上
|
9
SlipStupig 2016-12-19 02:41:10 +08:00 1
这种东西本身就是需要一个高 IO 的问题,有条件换成 HDFS (能配 ssd 就更好了) MapReduce 会快很多,不可能换的话,几个方面考虑:
1.使用 pypy 2.不要把文件下回来然后处理,最好能在远程处理完 3.视频读取媒体信息不需要完整读取的,所以直接解析文件头部就可以得到了,如果不想自己写解析函数,如果读取大文件的时候可以用 mmap 去读取而不是直接 fopen 4.用 gevent ,记得先得使用 monkey patch 否则无效 |
10
tinypig OP @SlipStupig
1. 使用扫描脚本是写在 Django admin 的 commands 里,方便操作数据库 :)所以之前没考虑用 pypy 2. 这个业务只是一个外部统计使用的,所以没有办法部署到相应的文件服务器上,只能通过网络挂载。 3. 我现在使用的获取媒体信息的库是 MediaInfo (对应的 pymediainfo ),看介绍他应该就是只下载一部分内容即可的,稍后我测试一下看看。 4. 这一点好像我忽略了,只是替换了它的 Pool ,稍后我尝试一下。 感谢。 |