python读取大文件md5校验性能优化比较

导读:本篇文章讲解 python读取大文件md5校验性能优化比较,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

with open(filename, "rb") as f:
  1. f.read() 读取整个文件,通常将文件内容放到一个字符串变量中;
  2. f.readline() 次读取一行内容;
  3. f.readlines() 一次性读取所有内容并按行返回list;
    当读取的文件较大时,全部读取内存中,会导致内存溢出

第一种:readline()

def md5_sum(filename):
    with open(filename, "rb") as f:
        f.seek(0)
        line = f.readline()

        md5 = hashlib.md5()
        md5.update(line)

        while line:
            line = f.readline()
            md5.update(line)

        f_md5 = md5.hexdigest()
    print(f_md5)
    return f_md5

我以一个1.4G的文件进行测试

4dcafe2e69d6d0a8979cb4eb7c26c3fd
耗时:  6.345685958862305
Current memory usage is 0.008476MB; Peak was 5.260233MB

耗时 6s,峰值内存占用5.2M

第二种:readlines()

def md5_sum2(filename):
    with open(filename, "rb") as f:
        f.seek(0)
        md5 = hashlib.md5()

        for line in f.readlines():
            md5.update(line)

        f_md5 = md5.hexdigest()
    print(f_md5)
    return f_md5

一次性将文件读到内存中,如果内存不够会报错

4dcafe2e69d6d0a8979cb4eb7c26c3fd
耗时:  7.258216857910156
Current memory usage is 0.008476MB; Peak was 1654.899472MB

耗时 7.2s,峰值内存占用1654M
反而速度更慢!

第三种:read()

def md5_sum3(filename):
    def chunked_file_reader(file, block_size=1024 * 16):
        """生成器函数:分块读取文件内容,使用 iter 函数
        """
        # 首先使用 partial(fp.read, block_size) 构造一个新的无需参数的函数
        # 循环将不断返回 fp.read(block_size) 调用结果,直到其为 '' 时终止
        for chunk in iter(partial(file.read, block_size), b''):
            yield chunk

    with open(filename, "rb") as f:
        f.seek(0)
        md5 = hashlib.md5()

        for line in chunked_file_reader(f):
            md5.update(line)

    f_md5 = md5.hexdigest()
    print(f_md5)
    return f_md5

利用read block_size读取大小限制,构造生成器

4dcafe2e69d6d0a8979cb4eb7c26c3fd
耗时:  3.0910959243774414
Current memory usage is 0.014733MB; Peak was 0.053139MB

耗时 3,峰值内存占用0.05M

第四种:read() + itertools

def md5_sum4(filename):
    buffer = 1024 * 1024

    with open(filename, "rb") as f:
        buf_gen = takewhile(lambda x: x, (f.read(buffer) for _ in repeat(None)))
        md5 = hashlib.md5()

        for line in buf_gen:
            md5.update(line)
    f_md5 = md5.hexdigest()
    print(f_md5)
    return f_md5

itertools 有更好的for loop 性能
这里切片大小设置为 1024*1024

4dcafe2e69d6d0a8979cb4eb7c26c3fd
耗时:  2.7328171730041504
Current memory usage is 0.00074MB; Peak was 2.103334MB

耗时 2.7s,峰值内存占用2.1M

总结

  1. 后端分片的话可以考虑多线程,多进程的处理方案
  2. 但是一般业务场景 更多是前端上传的文件流的形式
  3. 更好的方案是前端拆分大文件,后端在接受文件的同时算出md5

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48884.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!