zoukankan      html  css  js  c++  java
  • 记一次uboot中gunzip解压速度慢的问题排查

    背景

    在项目中需要用到解压功能,之前还记录了下,将uboot解压代码移植到另外的bootloader中时,碰到的效率问题。最终查明是cache的配置导致的。

    https://www.cnblogs.com/zqb-all/p/11443127.html

    优化前速度是uboot的十分之一,优化后速度达到uboot的两倍多。

    没想到风水轮流转,最近在uboot中用了解压功能,结果最终在进行启动速度优化时,发现解压速度很慢,

    不仅比不上移植到另一个bootloader中的解压速度,而且比之前测到过的uboot解压速度要慢得多。

    同样的数据量,在另一个bootloader中解压耗时低于200毫秒,而记忆中的之前测到的uboot中耗时为数百毫秒,最新数据测得是接近2秒。

    cache

    最开始还是怀疑cache,一顿操作一无所获,经过确认cache是确实使能了的,类型也是write-back,没有问题。为了确认还故意将其配置为write-through,测得性能进一步降低了,这才确认此路不通。

    watchdog

    继续排查,最终才性能问题是一个watchdog配置项引入的,打开了watchdog之后解压耗时就从数百毫秒增加到了接近2秒,足足三倍。

    watchdog怎么就影响到了解压速度呢?原来uboot在很多地方预置了watchdog的喂狗的钩子,当适配了watchdog驱动并使能之后,这些钩子就会生效,自动喂狗。

    现在的问题就出在,zlib库中也被预置了喂狗的钩子,这就导致watchdog使能之后,解压的循环中会不停喂狗,多出了不少开销。

    考虑到我们实际这块板子的watchdog超时时间长达16s,而解压的耗时在百毫秒级别,根本不需要考虑在解压过程喂狗,因此解决方式简单粗暴,将zlib中的喂狗操作全部去除即可。

    指定解压后长度

    搞定了watchdog之后速度提升不少,但还是比之前移植到另一个bootloader的解压慢,这个也不正常,于是进一步排查。

    最终发现,问题出在我们本次在uboot中调用gunzip时偷懒了,没有去解析解压前后文件的大小,直接将src_len和dst_len指定为~0UL。

    这是从unzip命令的实现中学的,默认 src_len = ~0UL, dst_len = ~0UL; 是否指定解压后文件大小是可选的

    本想简单些,让解压库自行处理,反正我们已经分配了足够的大小,肯定不会越界,没想到不指定还会带来效率问题。

    解决方法,从压缩包的尾部读出压缩前的原始文件大小,解压时作为参数传给gunzip函数。

    下面是直接在控制台调用unzip命令,使用minicom的时间戳,来演示带长度和不带长度的区别

    只指定源地址和目的地址,则耗时约430ms

    [2019-11-25 09:59:43.014] => version;unzip 40901000 40000000
    [2019-11-25 10:00:10.359] U-Boot 2018.05 (Nov 25 2019 - 09:20:58 +0800) Allwinner Technology
    [2019-11-25 10:00:10.385] 
    [2019-11-25 10:00:10.385] arm-linux-gnueabi-gcc (Linaro GCC 7.2-2017.11) 7.2.1 20171011
    [2019-11-25 10:00:10.385] GNU ld (Linaro_Binutils-2017.11) 2.28.2.20170706
    [2019-11-25 10:00:10.815] Uncompressed size: 6553388 = 0x63FF2C
    

    指定源地址和目的地址,同时指定长度,则耗时约170ms

    [2019-11-25 10:00:10.831] => version;unzip 40901000 40000000 0x63FF2C
    [2019-11-25 10:00:30.486] U-Boot 2018.05 (Nov 25 2019 - 09:20:58 +0800) Allwinner Technology
    [2019-11-25 10:00:30.486] 
    [2019-11-25 10:00:30.486] arm-linux-gnueabi-gcc (Linaro GCC 7.2-2017.11) 7.2.1 20171011
    [2019-11-25 10:00:30.487] GNU ld (Linaro_Binutils-2017.11) 2.28.2.20170706
    [2019-11-25 10:00:30.646] Uncompressed size: 6553388 = 0x63FF2C
    

    本文链接 https://www.cnblogs.com/zqb-all/p/11966601.html

  • 相关阅读:
    Redis开发与运维:SDS
    Redis开发与运维:数据迁移
    我的2019上半年
    C# 并发编程
    经典排序算法 — C# 版(上)
    图解 -- 树的汇总
    图解--队列、并发队列
    栈到CLR
    我们的数组
    算法复杂度
  • 原文地址:https://www.cnblogs.com/zqb-all/p/11966601.html
Copyright © 2011-2022 走看看